1366 lines
42 KiB
C#
1366 lines
42 KiB
C#
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
//
|
|||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|||
|
//
|
|||
|
// Microsoft Research Singularity
|
|||
|
//
|
|||
|
|
|||
|
using System;
|
|||
|
using System.Collections;
|
|||
|
using System.Diagnostics;
|
|||
|
using System.Text;
|
|||
|
|
|||
|
using TermObj = Microsoft.Singularity.Hal.Acpi.AmlParserUnions.TermObj;
|
|||
|
using Microsoft.Singularity.Hal.Acpi.StackIR;
|
|||
|
using Microsoft.Singularity.Hal.Acpi.AmlParserUnions;
|
|||
|
|
|||
|
namespace Microsoft.Singularity.Hal.Acpi.AcpiObject
|
|||
|
{
|
|||
|
//
|
|||
|
// Based roughly on Table 17-6 from the ACPI Specification 3.0b, the
|
|||
|
// following class hierarchy describes ACPI objects, which constitute
|
|||
|
// the values assigned to each named node in the ACPI namespace as well
|
|||
|
// as all values assigned to temporary objects, local objects, and so on.
|
|||
|
// They are created and used at both load time and run time.
|
|||
|
//
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Values returned by ObjectType operator as described in section
|
|||
|
/// 17.5.86 of the ACPI specification 3.0b.
|
|||
|
/// </summary>
|
|||
|
public enum AcpiObjectType
|
|||
|
{
|
|||
|
Uninitialized = 0,
|
|||
|
Integer = 1,
|
|||
|
String = 2,
|
|||
|
Buffer = 3,
|
|||
|
Package = 4,
|
|||
|
FieldUnit = 5,
|
|||
|
Device = 6,
|
|||
|
Event = 7,
|
|||
|
Method = 8,
|
|||
|
Mutex = 9,
|
|||
|
OperationRegion = 10,
|
|||
|
PowerResource = 11,
|
|||
|
Processor = 12,
|
|||
|
ThermalZone = 13,
|
|||
|
BufferField = 14,
|
|||
|
DdbHandle = 15,
|
|||
|
DebugObject = 16
|
|||
|
}
|
|||
|
|
|||
|
public abstract class AcpiObject
|
|||
|
{
|
|||
|
public abstract Integer ObjectType();
|
|||
|
|
|||
|
public abstract void Write(AcpiObject value);
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Get the value referred to by this value, for creating indirection.
|
|||
|
/// Returns self for concrete types.
|
|||
|
/// </summary>
|
|||
|
public virtual AcpiObject GetTarget()
|
|||
|
{
|
|||
|
return this;
|
|||
|
}
|
|||
|
|
|||
|
public virtual Integer GetAsInt()
|
|||
|
{
|
|||
|
throw new AmlTypeException();
|
|||
|
}
|
|||
|
|
|||
|
public virtual String GetAsString()
|
|||
|
{
|
|||
|
throw new AmlTypeException();
|
|||
|
}
|
|||
|
|
|||
|
public virtual Buffer GetAsBuffer()
|
|||
|
{
|
|||
|
throw new AmlTypeException();
|
|||
|
}
|
|||
|
|
|||
|
public virtual Method GetAsMethod()
|
|||
|
{
|
|||
|
throw new AmlTypeException();
|
|||
|
}
|
|||
|
|
|||
|
public virtual Mutex GetAsMutex()
|
|||
|
{
|
|||
|
throw new AmlTypeException();
|
|||
|
}
|
|||
|
|
|||
|
public virtual Device GetAsDevice()
|
|||
|
{
|
|||
|
throw new AmlTypeException();
|
|||
|
}
|
|||
|
|
|||
|
public virtual ulong Size
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
throw new AmlTypeException();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public virtual AcpiObject Dereference()
|
|||
|
{
|
|||
|
throw new AmlTypeException();
|
|||
|
}
|
|||
|
|
|||
|
public virtual AcpiObject Index(ulong index)
|
|||
|
{
|
|||
|
throw new AmlTypeException();
|
|||
|
}
|
|||
|
|
|||
|
public virtual AcpiObject[] GetObjects()
|
|||
|
{
|
|||
|
throw new AmlTypeException();
|
|||
|
}
|
|||
|
|
|||
|
public virtual void SetIndex(ulong index, AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Contains a reference to an AcpiObject - this added level of indirection
|
|||
|
/// is necessary to permit AcpiObject objects to be modified through
|
|||
|
/// ObjectReference objects.
|
|||
|
/// </summary>
|
|||
|
public class AcpiObjectCell
|
|||
|
{
|
|||
|
AcpiObject containedValue;
|
|||
|
|
|||
|
public AcpiObjectCell(AcpiObject containedValue)
|
|||
|
{
|
|||
|
this.containedValue = containedValue;
|
|||
|
}
|
|||
|
|
|||
|
public AcpiObject Value
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return containedValue;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
if (containedValue is UninitializedObject) {
|
|||
|
containedValue = value;
|
|||
|
}
|
|||
|
else {
|
|||
|
containedValue.Write(value);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An uninitialized ACPI object.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: No assigned type or value. This is the type
|
|||
|
/// of all control method LocalX variables and unused ArgX variables at
|
|||
|
/// the beginning of method execution, as well as all uninitialized
|
|||
|
/// Package elements. Uninitialized objects must be initialized (via
|
|||
|
/// Store or CopyObject) before they may be used as source operands in
|
|||
|
/// ASL expressions.</remarks>
|
|||
|
public class UninitializedObject : AcpiObject
|
|||
|
{
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.Uninitialized);
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException("Cannot write to uninitialized object");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI buffer object representing an array of bytes.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: An array of bytes. Uninitialized elements
|
|||
|
/// are zero by default.</remarks>
|
|||
|
public class Buffer : AcpiObject
|
|||
|
{
|
|||
|
byte[] contents;
|
|||
|
|
|||
|
public Buffer(byte[] contents)
|
|||
|
{
|
|||
|
this.contents = contents;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.Buffer);
|
|||
|
}
|
|||
|
|
|||
|
public override AcpiObject Index(ulong index)
|
|||
|
{
|
|||
|
return new Integer(contents[index]);
|
|||
|
}
|
|||
|
|
|||
|
public override void SetIndex(ulong index, AcpiObject value)
|
|||
|
{
|
|||
|
contents[index] = (byte)value.GetAsInt().Value;
|
|||
|
}
|
|||
|
|
|||
|
public byte[] Contents
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return (byte[])contents.Clone();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public override Buffer GetAsBuffer()
|
|||
|
{
|
|||
|
return this;
|
|||
|
}
|
|||
|
|
|||
|
public override string ToString()
|
|||
|
{
|
|||
|
StringBuilder result = new StringBuilder();
|
|||
|
result.Append("{");
|
|||
|
bool first = true;
|
|||
|
foreach (byte b in contents) {
|
|||
|
if (first) {
|
|||
|
first = false;
|
|||
|
}
|
|||
|
else {
|
|||
|
result.Append(", ");
|
|||
|
}
|
|||
|
result.Append(b.ToString("x"));
|
|||
|
}
|
|||
|
result.Append("}");
|
|||
|
return result.ToString();
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException("TODO");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI buffer field object representing a portion of a buffer.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Portion of a buffer created using
|
|||
|
/// CreateBitField, CreateByteField, CreateWordField, CreateQWordField,
|
|||
|
/// CreateField, or returned by the Index operator.</remarks>
|
|||
|
public class BufferField : AcpiObject
|
|||
|
{
|
|||
|
AcpiObject sourceBuffer = null;
|
|||
|
ulong startBitIndex;
|
|||
|
ulong numBits;
|
|||
|
|
|||
|
public BufferField(AcpiObject sourceBuffer, ulong startBitIndex, ulong numBits)
|
|||
|
{
|
|||
|
if (numBits > sizeof(ulong) * 8) {
|
|||
|
throw new AmlTypeException("Tried to create field with more than maximum number of bits");
|
|||
|
}
|
|||
|
|
|||
|
this.sourceBuffer = sourceBuffer;
|
|||
|
this.startBitIndex = startBitIndex;
|
|||
|
this.numBits = numBits;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.BufferField);
|
|||
|
}
|
|||
|
|
|||
|
public override Integer GetAsInt()
|
|||
|
{
|
|||
|
return (Integer)Dereference();
|
|||
|
}
|
|||
|
|
|||
|
public override AcpiObject Dereference()
|
|||
|
{
|
|||
|
if ((startBitIndex % 8) != 0 || (numBits % 8) != 0) {
|
|||
|
throw new AmlTypeException("TODO: Non-byte-aligned buffer fields");
|
|||
|
}
|
|||
|
|
|||
|
ulong result = 0;
|
|||
|
// Loop from first byte to last
|
|||
|
for(ulong idx = startBitIndex/8u; idx < startBitIndex/8u + numBits/8u; idx++) {
|
|||
|
result = (result << 8) | sourceBuffer.Index(idx).GetAsInt().Value;
|
|||
|
}
|
|||
|
return new Integer(result);
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject valueObj)
|
|||
|
{
|
|||
|
if ((startBitIndex % 8) != 0 || (numBits % 8) != 0) {
|
|||
|
throw new AmlTypeException("TODO: Non-byte-aligned buffer fields");
|
|||
|
}
|
|||
|
|
|||
|
ulong value = valueObj.GetAsInt().Value;
|
|||
|
|
|||
|
// We ignore high bits above the number of bits fitting in the field.
|
|||
|
// Used to check this, but some code actually depends on the behavior of
|
|||
|
// truncating high bits, like this from VPC:
|
|||
|
|
|||
|
// Method (_CRS, 0, NotSerialized)
|
|||
|
// {
|
|||
|
// CreateDWordField (CRS, \_SB.SYSM._Y10._BAS, BAS4)
|
|||
|
// CreateDWordField (CRS, \_SB.SYSM._Y10._LEN, LEN4)
|
|||
|
// Subtract (0x00, BAS4, LEN4)
|
|||
|
// }
|
|||
|
|
|||
|
// NB write in little endian byte-order
|
|||
|
ulong end = startBitIndex/8u + numBits/8u;
|
|||
|
for (ulong idx = startBitIndex / 8u; idx < end; idx++) {
|
|||
|
sourceBuffer.SetIndex(idx, new Integer(value & 0xFF));
|
|||
|
value >>= 8;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI DDB handle object referring to a Differentiated Definition Block.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Definition block handle returned
|
|||
|
/// by the Load operator [and passed to the Unload operator].</remarks>
|
|||
|
public class DdbHandle : AcpiObject
|
|||
|
{
|
|||
|
// TODO: The representation of this will come from the table loading code
|
|||
|
// and depend on the implementation of Load and Unload.
|
|||
|
|
|||
|
private DdbHandle() { } // Prevent construction until completed
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.DdbHandle);
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException("TODO");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI debug object used for formatting and printing debug output.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Debug output object. Formats an object
|
|||
|
/// and prints it to the system debug port. Has no effect if debugging
|
|||
|
/// is not active. Section 17.5.23: The debug data object is a virtual
|
|||
|
/// data object. Writes to this object provide debugging information.
|
|||
|
/// On at least debug versions of the interpreter, any writes into this
|
|||
|
/// object are appropriately displayed on the system<65>s native kernel
|
|||
|
/// debugger. All writes to the debug object are otherwise benign. If
|
|||
|
/// the system is in use without a kernel debugger, then writes to the
|
|||
|
/// debug object are ignored.</remarks>
|
|||
|
public class DebugObject : AcpiObject
|
|||
|
{
|
|||
|
private DebugObject() { }
|
|||
|
|
|||
|
public readonly DebugObject Instance = new DebugObject();
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.DebugObject);
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
#if SINGULARITY_KERNEL
|
|||
|
DebugStub.Write(value.ToString());
|
|||
|
#else
|
|||
|
Console.Write(value.ToString());
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI device object representing a device or bus.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Device or bus object</remarks>
|
|||
|
public class Device : AcpiObject
|
|||
|
{
|
|||
|
AcpiNamespace.AbsoluteNodePath path;
|
|||
|
|
|||
|
public Device(AcpiNamespace.AbsoluteNodePath path)
|
|||
|
{
|
|||
|
this.path = path;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.Device);
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException("TODO");
|
|||
|
}
|
|||
|
|
|||
|
public AcpiNamespace.AbsoluteNodePath Path
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return path;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public override Device GetAsDevice()
|
|||
|
{
|
|||
|
return this;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI event synchronization object
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Event synchronization object</remarks>
|
|||
|
public class Event : AcpiObject
|
|||
|
{
|
|||
|
public Event()
|
|||
|
{
|
|||
|
// No data - an event is described entirely by its name
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.Event);
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException("TODO");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Enums based on FieldFlags rule in AML grammar,
|
|||
|
// ACPI specification 3.0b section 18.2.5.2
|
|||
|
//
|
|||
|
|
|||
|
public enum AccessType
|
|||
|
{
|
|||
|
AnyAcc = 0,
|
|||
|
ByteAcc = 1,
|
|||
|
WordAcc = 2,
|
|||
|
DWordAcc = 3,
|
|||
|
QWordAcc = 4,
|
|||
|
BufferAcc = 5,
|
|||
|
Reserved1 = 6,
|
|||
|
Reserved2 = 7,
|
|||
|
Reserved3 = 8,
|
|||
|
Reserved4 = 9,
|
|||
|
Reserved5 = 10,
|
|||
|
Reserved6 = 11,
|
|||
|
Reserved7 = 12,
|
|||
|
Reserved8 = 13,
|
|||
|
Reserved9 = 14,
|
|||
|
Reserved10 = 15
|
|||
|
}
|
|||
|
|
|||
|
public enum LockRule
|
|||
|
{
|
|||
|
NoLock = 0,
|
|||
|
Lock = 1
|
|||
|
}
|
|||
|
|
|||
|
public enum UpdateRule
|
|||
|
{
|
|||
|
Preserved = 0,
|
|||
|
WriteAsOnes = 1,
|
|||
|
WriteAsZeros = 2,
|
|||
|
Invalid = 3
|
|||
|
}
|
|||
|
|
|||
|
public enum AccessAttrib
|
|||
|
{
|
|||
|
SMBNone = 0x00,
|
|||
|
SMBQuick = 0x02,
|
|||
|
SMBSendReceive = 0x04,
|
|||
|
SMBByte = 0x06,
|
|||
|
SMBWord = 0x08,
|
|||
|
SMBBlock = 0x0A,
|
|||
|
SMBProcessCall = 0x0C,
|
|||
|
SMBBlockProcessCall = 0x0D
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI field unit object referring to a portion of an address space.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: (within an Operation Region) Portion of an
|
|||
|
/// address space, bit-aligned and of one-bit granularity. Created using
|
|||
|
/// Field, BankField, or IndexField.</remarks>
|
|||
|
public class FieldUnit : AcpiObject
|
|||
|
{
|
|||
|
OperationRegion operationRegion;
|
|||
|
int startBitIndex;
|
|||
|
int numBits;
|
|||
|
AccessType accessType;
|
|||
|
AccessAttrib accessAttrib;
|
|||
|
LockRule lockRule;
|
|||
|
UpdateRule updateRule;
|
|||
|
|
|||
|
public FieldUnit(OperationRegion operationRegion, int startBitIndex, int numBits,
|
|||
|
AccessType accessType, AccessAttrib accessAttrib,
|
|||
|
LockRule lockRule, UpdateRule updateRule)
|
|||
|
{
|
|||
|
if (startBitIndex < 0 || (startBitIndex + numBits + 7)/8 > (int)operationRegion.Length) {
|
|||
|
throw new ArgumentException("Field unit not in bounds of operation region");
|
|||
|
}
|
|||
|
|
|||
|
this.operationRegion = operationRegion;
|
|||
|
this.startBitIndex = startBitIndex;
|
|||
|
this.numBits = numBits;
|
|||
|
this.accessType = accessType;
|
|||
|
this.accessAttrib = accessAttrib;
|
|||
|
this.lockRule = lockRule;
|
|||
|
this.updateRule = updateRule;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer GetAsInt()
|
|||
|
{
|
|||
|
return new Integer(Read());
|
|||
|
}
|
|||
|
|
|||
|
public override Buffer GetAsBuffer()
|
|||
|
{
|
|||
|
if ((startBitIndex % 8) == 0) {
|
|||
|
return new Buffer(operationRegion.ReadBytes((ulong)(startBitIndex / 8),
|
|||
|
(ulong)(numBits + 7)/8));
|
|||
|
}
|
|||
|
else {
|
|||
|
throw new Exception("Unimplemented conversion of unaligned field to buffer");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public ulong Read()
|
|||
|
{
|
|||
|
if (numBits == 8 && (startBitIndex % 8) == 0) {
|
|||
|
return operationRegion.Read8At((ulong)(startBitIndex / 8));
|
|||
|
}
|
|||
|
else if (numBits == 16 && (startBitIndex % 8) == 0) {
|
|||
|
return operationRegion.Read16At((ulong)(startBitIndex / 8));
|
|||
|
}
|
|||
|
else if (numBits == 32 && (startBitIndex % 8) == 0) {
|
|||
|
return operationRegion.Read32At((ulong)(startBitIndex / 8));
|
|||
|
}
|
|||
|
else {
|
|||
|
// Small field or unaligned, do general case
|
|||
|
int bitIndex = startBitIndex;
|
|||
|
int remainingBits = numBits;
|
|||
|
|
|||
|
uint result = 0;
|
|||
|
while (remainingBits > 0) {
|
|||
|
byte b = operationRegion.Read8At((ulong)(bitIndex / 8));
|
|||
|
for (int bitInWord = bitIndex % 8;
|
|||
|
bitInWord < 8 && remainingBits > 0;
|
|||
|
bitInWord++, bitIndex++, remainingBits--) {
|
|||
|
result = (result << 1) | (uint)((b >> (7 - bitInWord)) & 1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// This is currently just used by IndexField, will probably become accessible
|
|||
|
/// from AML when implementing stores.
|
|||
|
/// </summary>
|
|||
|
public override void Write(AcpiObject valueObj)
|
|||
|
{
|
|||
|
ulong value = valueObj.GetAsInt().Value;
|
|||
|
|
|||
|
Debug.Assert(AcpiObjectUtils.GetNumBits(value) <= (ulong)numBits, "Writing value too large for field");
|
|||
|
|
|||
|
if (numBits == 8 && (startBitIndex % 8) == 0) {
|
|||
|
operationRegion.Write8At((ulong)(startBitIndex / 8), (byte)value);
|
|||
|
}
|
|||
|
else if (numBits == 16 && (startBitIndex % 8) == 0) {
|
|||
|
operationRegion.Write16At((ulong)(startBitIndex / 8), (byte)value);
|
|||
|
}
|
|||
|
else if (numBits == 32 && (startBitIndex % 8) == 0) {
|
|||
|
operationRegion.Write32At((ulong)(startBitIndex / 8), (byte)value);
|
|||
|
}
|
|||
|
else {
|
|||
|
throw new Exception("Unimplemented operation region field size");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.FieldUnit);
|
|||
|
}
|
|||
|
|
|||
|
// SortedList will be Dictionary<string, FieldUnit> when generics are available
|
|||
|
public static SortedList CreateFromFieldList(OperationRegion operationRegionNode,
|
|||
|
FieldElement[] fieldList,
|
|||
|
AccessType initialAccessType,
|
|||
|
AccessAttrib initialAccessAttrib,
|
|||
|
LockRule lockRule,
|
|||
|
UpdateRule updateRule
|
|||
|
)
|
|||
|
{
|
|||
|
SortedList result = new SortedList(); // = new Dictionary<string, FieldUnit>();
|
|||
|
AccessType accessType = initialAccessType;
|
|||
|
AccessAttrib accessAttrib = initialAccessAttrib;
|
|||
|
int bitIndex = 0;
|
|||
|
|
|||
|
foreach (FieldElement fieldElement in fieldList) {
|
|||
|
switch (fieldElement.Tag) {
|
|||
|
case FieldElement.TagValue.NamedField:
|
|||
|
AmlParser.NamedField namedField = fieldElement.GetAsNamedField();
|
|||
|
result.Add(namedField.nameSeg.data,
|
|||
|
new FieldUnit(operationRegionNode,
|
|||
|
bitIndex, namedField.bitWidth,
|
|||
|
accessType, accessAttrib, lockRule, updateRule));
|
|||
|
bitIndex += namedField.bitWidth;
|
|||
|
break;
|
|||
|
case FieldElement.TagValue.ReservedField:
|
|||
|
AmlParser.ReservedField reservedField = fieldElement.GetAsReservedField();
|
|||
|
bitIndex += reservedField.bitWidth;
|
|||
|
break;
|
|||
|
case FieldElement.TagValue.AccessField:
|
|||
|
AmlParser.AccessField accessField = fieldElement.GetAsAccessField();
|
|||
|
accessType = accessField.accessType;
|
|||
|
accessAttrib = accessField.accessAttrib;
|
|||
|
break;
|
|||
|
default:
|
|||
|
throw new LoadException("Unhandled alternative in switch over 'FieldElement'");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// This operation region accessor accesses internal device registers
|
|||
|
/// through an index/data pair (typically a pair of I/O ports inside an
|
|||
|
/// I/O operation region). It is used by IndexField definitions, which
|
|||
|
/// create FieldUnits inside these internal operation regions. The
|
|||
|
/// RegionSpace type is ignored.
|
|||
|
/// </summary>
|
|||
|
public class IndexFieldOperationRegionAccessor : IOperationRegionAccessor
|
|||
|
{
|
|||
|
FieldUnit index;
|
|||
|
FieldUnit data;
|
|||
|
|
|||
|
public IndexFieldOperationRegionAccessor(FieldUnit index, FieldUnit data)
|
|||
|
{
|
|||
|
this.index = index;
|
|||
|
this.data = data;
|
|||
|
}
|
|||
|
|
|||
|
public byte Read8(RegionSpace regionSpace, ulong offset)
|
|||
|
{
|
|||
|
index.Write(new Integer(offset));
|
|||
|
return (byte)data.Read();
|
|||
|
}
|
|||
|
|
|||
|
public void Write8(RegionSpace regionSpace, ulong offset, byte value)
|
|||
|
{
|
|||
|
index.Write(new Integer(offset));
|
|||
|
data.Write(new Integer(value));
|
|||
|
}
|
|||
|
|
|||
|
public ushort Read16(RegionSpace regionSpace, ulong offset)
|
|||
|
{
|
|||
|
index.Write(new Integer(offset));
|
|||
|
return (ushort)data.Read();
|
|||
|
}
|
|||
|
|
|||
|
public void Write16(RegionSpace regionSpace, ulong offset, ushort value)
|
|||
|
{
|
|||
|
index.Write(new Integer(offset));
|
|||
|
data.Write(new Integer(value));
|
|||
|
}
|
|||
|
|
|||
|
public uint Read32(RegionSpace regionSpace, ulong offset)
|
|||
|
{
|
|||
|
index.Write(new Integer(offset));
|
|||
|
return (uint)data.Read();
|
|||
|
}
|
|||
|
|
|||
|
public void Write32(RegionSpace regionSpace, ulong offset, uint value)
|
|||
|
{
|
|||
|
index.Write(new Integer(offset));
|
|||
|
data.Write(new Integer(value));
|
|||
|
}
|
|||
|
|
|||
|
public byte[] ReadBytes(RegionSpace regionSpace, ulong offset, ulong length)
|
|||
|
{
|
|||
|
throw new Exception("Unimplemented ReadBytes() from index field");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI integer object
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: An n-bit little-endian unsigned integer.
|
|||
|
/// In ACPI 1.0 this was at least 32 bits. In ACPI 2.0 and later, this
|
|||
|
/// is 64 bits.</remarks>
|
|||
|
public class Integer : AcpiObject
|
|||
|
{
|
|||
|
ulong value;
|
|||
|
|
|||
|
public Integer(ulong value)
|
|||
|
{
|
|||
|
this.value = value;
|
|||
|
}
|
|||
|
|
|||
|
public ulong Value
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return value;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.Integer);
|
|||
|
}
|
|||
|
|
|||
|
public override Integer GetAsInt()
|
|||
|
{
|
|||
|
if (this == IntegerConstant.Zero ||
|
|||
|
this == IntegerConstant.One ||
|
|||
|
this == IntegerConstant.Ones) {
|
|||
|
// Reading an IntegerConstant does not get the singleton object
|
|||
|
// but just the value in it.
|
|||
|
return new Integer(value);
|
|||
|
}
|
|||
|
return this;
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
if (this == IntegerConstant.Zero ||
|
|||
|
this == IntegerConstant.One ||
|
|||
|
this == IntegerConstant.Ones) {
|
|||
|
throw new AmlTypeException("Cannot write to reserved integer constant objects");
|
|||
|
}
|
|||
|
this.value = value.GetAsInt().Value;
|
|||
|
}
|
|||
|
|
|||
|
public override string ToString()
|
|||
|
{
|
|||
|
return value.ToString();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Wrapper class for some static methods referring to ACPI integer
|
|||
|
/// constant built-in integer constants.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Created by the ASL terms "Zero", "One",
|
|||
|
/// "Ones", and "Revision". We did not create a subclass for these
|
|||
|
/// because ObjectType has no "IntegerConstant" type, only Integer.</remarks>
|
|||
|
public class IntegerConstant
|
|||
|
{
|
|||
|
private IntegerConstant() { } // Don't allow construction
|
|||
|
|
|||
|
public readonly static Integer Zero = new Integer(0UL);
|
|||
|
public readonly static Integer One = new Integer(1UL);
|
|||
|
public readonly static Integer Ones = new Integer(~(0UL));
|
|||
|
public readonly static Integer Revision = new Integer(0); // TODO: What's the right value for this?
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Enum based on MethodFlags rule in AML grammar,
|
|||
|
// ACPI specification 3.0b section 18.2.5.2
|
|||
|
//
|
|||
|
|
|||
|
public enum SerializeFlag
|
|||
|
{
|
|||
|
NotSerialized = 0,
|
|||
|
Serialized = 1
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI method object referring to an invokable method.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Control Method (Executable AML function)</remarks>
|
|||
|
public abstract class Method : AcpiObject
|
|||
|
{
|
|||
|
byte argCount;
|
|||
|
SerializeFlag serializeFlag;
|
|||
|
byte syncLevel;
|
|||
|
|
|||
|
public Method(byte argCount, SerializeFlag serializeFlag, byte syncLevel)
|
|||
|
{
|
|||
|
this.argCount = argCount;
|
|||
|
this.serializeFlag = serializeFlag;
|
|||
|
this.syncLevel = syncLevel;
|
|||
|
}
|
|||
|
|
|||
|
public byte ArgCount
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return argCount;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.Method);
|
|||
|
}
|
|||
|
|
|||
|
public override Method GetAsMethod()
|
|||
|
{
|
|||
|
return this;
|
|||
|
}
|
|||
|
|
|||
|
public abstract void Invoke(AmlInterpreterThread thread, AcpiObject[] parameters, AcpiNamespace acpiNamespace);
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException("Cannot write to method");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// A method whose body is represented using AML bytecode which can be parsed
|
|||
|
/// and interpreted.
|
|||
|
/// </summary>
|
|||
|
public class BytecodeMethod : Method
|
|||
|
{
|
|||
|
byte[] unparsedTermList;
|
|||
|
StackIRNode[] body;
|
|||
|
|
|||
|
public BytecodeMethod(byte argCount, SerializeFlag serializeFlag, byte syncLevel, byte[] unparsedTermList)
|
|||
|
: base(argCount, serializeFlag, syncLevel)
|
|||
|
{
|
|||
|
this.unparsedTermList = unparsedTermList;
|
|||
|
this.body = null;
|
|||
|
}
|
|||
|
|
|||
|
public AmlParser.ParseSuccess Parse(AcpiNamespace acpiNamespace, AcpiNamespace.AbsoluteNodePath initialNodePath)
|
|||
|
{
|
|||
|
int offset = 0;
|
|||
|
TermObj[] termList;
|
|||
|
if (new AmlParser(new ByteBufferAmlStreamAdapter(unparsedTermList), acpiNamespace, initialNodePath).
|
|||
|
ParseTermList(out termList, ref offset, unparsedTermList.Length) == AmlParser.ParseSuccess.Failure) {
|
|||
|
return AmlParser.ParseSuccess.Failure;
|
|||
|
}
|
|||
|
Debug.Assert(offset == unparsedTermList.Length, "offset == unparsedTermList.Length");
|
|||
|
|
|||
|
AmlToStackIRVisitor amlToStackIRVisitor = new AmlToStackIRVisitor();
|
|||
|
amlToStackIRVisitor.VisitSequence(termList);
|
|||
|
body = amlToStackIRVisitor.Result;
|
|||
|
|
|||
|
return AmlParser.ParseSuccess.Success;
|
|||
|
}
|
|||
|
|
|||
|
public override void Invoke(AmlInterpreterThread thread, AcpiObject[] parameters, AcpiNamespace acpiNamespace)
|
|||
|
{
|
|||
|
if (body == null) {
|
|||
|
AcpiNamespace.Node node = acpiNamespace.FindValue(this);
|
|||
|
if (Parse(acpiNamespace, node.Path) == AmlParser.ParseSuccess.Failure) {
|
|||
|
throw new InterpretException("AML parser failure while just-in-time parsing AML method body");
|
|||
|
}
|
|||
|
}
|
|||
|
thread.PushFrame(new AmlStackFrame(body, parameters));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// A reserved method implemented directly by the operating system.
|
|||
|
/// </summary>
|
|||
|
public class ReservedMethod : Method
|
|||
|
{
|
|||
|
public delegate AcpiObject AcpiMethodImpl(AcpiObject[] arguments);
|
|||
|
|
|||
|
private AcpiMethodImpl impl;
|
|||
|
|
|||
|
public ReservedMethod(byte argCount, SerializeFlag serializeFlag, byte syncLevel, AcpiMethodImpl impl)
|
|||
|
: base(argCount, serializeFlag, syncLevel)
|
|||
|
{
|
|||
|
this.impl = impl;
|
|||
|
}
|
|||
|
|
|||
|
public override void Invoke(AmlInterpreterThread thread, AcpiObject[] parameters, AcpiNamespace acpiNamespace)
|
|||
|
{
|
|||
|
thread.Push(new ValueIoLocation(impl(parameters)));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI mutex synchronization object
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Mutex synchronization object</remarks>
|
|||
|
public class Mutex : AcpiObject
|
|||
|
{
|
|||
|
private class AmlInterpreterThreadSet : IEnumerable
|
|||
|
{
|
|||
|
ArrayList set = new ArrayList();
|
|||
|
|
|||
|
public void Add(AmlInterpreterThread thread) {
|
|||
|
set.Add(thread);
|
|||
|
}
|
|||
|
|
|||
|
public IEnumerator GetEnumerator() {
|
|||
|
return set.GetEnumerator();
|
|||
|
}
|
|||
|
|
|||
|
public void Clear() {
|
|||
|
set.Clear();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
byte syncLevel;
|
|||
|
AmlInterpreterThread owner = null;
|
|||
|
AmlInterpreterThreadSet waitingThreads = new AmlInterpreterThreadSet();
|
|||
|
|
|||
|
public Mutex(byte syncLevel)
|
|||
|
{
|
|||
|
this.syncLevel = syncLevel;
|
|||
|
}
|
|||
|
|
|||
|
public void Acquire(AmlInterpreterThread thread) {
|
|||
|
if (owner == null) {
|
|||
|
owner = thread;
|
|||
|
}
|
|||
|
else {
|
|||
|
waitingThreads.Add(thread);
|
|||
|
thread.Block();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void Release(AmlInterpreterThread thread) {
|
|||
|
if (owner == null) {
|
|||
|
throw new InterpretException("Attempt to release unlocked mutex");
|
|||
|
}
|
|||
|
owner = null;
|
|||
|
|
|||
|
foreach (AmlInterpreterThread waitingThread in waitingThreads) {
|
|||
|
waitingThread.Notify();
|
|||
|
}
|
|||
|
waitingThreads.Clear();
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.Mutex);
|
|||
|
}
|
|||
|
|
|||
|
public override Mutex GetAsMutex()
|
|||
|
{
|
|||
|
return this;
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException("Cannot write to mutex");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// See AmlLoader.LoadTimeEvaluate(AmlParser.UserTermObj userTermObj)
|
|||
|
/// for an explanation of the existence of this object type, which is
|
|||
|
/// not defined in the specification.
|
|||
|
/// </summary>
|
|||
|
public class NodePathReference : AcpiObject
|
|||
|
{
|
|||
|
private AcpiNamespace acpiNamespace;
|
|||
|
private AcpiNamespace.AbsoluteNodePath nodePath;
|
|||
|
|
|||
|
public NodePathReference(AcpiNamespace acpiNamespace,
|
|||
|
AcpiNamespace.AbsoluteNodePath nodePath)
|
|||
|
{
|
|||
|
this.acpiNamespace = acpiNamespace;
|
|||
|
this.nodePath = nodePath;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return GetTarget().ObjectType();
|
|||
|
}
|
|||
|
|
|||
|
public override AcpiObject GetTarget()
|
|||
|
{
|
|||
|
return acpiNamespace.LookupNode(nodePath).Value;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer GetAsInt()
|
|||
|
{
|
|||
|
return GetTarget().GetAsInt();
|
|||
|
}
|
|||
|
|
|||
|
public override Device GetAsDevice()
|
|||
|
{
|
|||
|
return GetTarget().GetAsDevice();
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
GetTarget().Write(value);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI object reference object referring to some other AcpiObject
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Reference to an object created using the
|
|||
|
/// RefOf, Index, or CondRefOf operators</remarks>
|
|||
|
public class ObjectReference : AcpiObject
|
|||
|
{
|
|||
|
AcpiObjectCell target;
|
|||
|
|
|||
|
public ObjectReference(AcpiObjectCell target)
|
|||
|
{
|
|||
|
this.target = target;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
// From 17.5.86: if this operation is performed on an object
|
|||
|
// reference [...] the object type of the base object is returned.
|
|||
|
return GetTarget().ObjectType();
|
|||
|
}
|
|||
|
|
|||
|
public override AcpiObject GetTarget()
|
|||
|
{
|
|||
|
return target.Value;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer GetAsInt()
|
|||
|
{
|
|||
|
return GetTarget().GetAsInt();
|
|||
|
}
|
|||
|
|
|||
|
public override Device GetAsDevice()
|
|||
|
{
|
|||
|
return GetTarget().GetAsDevice();
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
GetTarget().Write(value);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// From 17.5.89, describes the built-in region spaces in which an
|
|||
|
/// operation region can be created.
|
|||
|
/// </summary>
|
|||
|
public enum RegionSpace
|
|||
|
{
|
|||
|
SystemMemory = 0,
|
|||
|
SystemIO = 1,
|
|||
|
PCI_Config = 2,
|
|||
|
EmbeddedControl = 3,
|
|||
|
SMBus = 4,
|
|||
|
CMOS = 5,
|
|||
|
PCIBARTarget = 6
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Abstracts away reading of operation regions such as arbitrary
|
|||
|
/// memory read/writes, I/O, and PCI configuration space access.
|
|||
|
/// </summary>
|
|||
|
public interface IOperationRegionAccessor
|
|||
|
{
|
|||
|
byte[] ReadBytes(RegionSpace regionSpace, ulong offset, ulong length);
|
|||
|
byte Read8(RegionSpace regionSpace, ulong offset);
|
|||
|
void Write8(RegionSpace regionSpace, ulong offset, byte value);
|
|||
|
ushort Read16(RegionSpace regionSpace, ulong offset);
|
|||
|
void Write16(RegionSpace regionSpace, ulong offset, ushort value);
|
|||
|
uint Read32(RegionSpace regionSpace, ulong offset);
|
|||
|
void Write32(RegionSpace regionSpace, ulong offset, uint value);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI operation region object, representing a region within an
|
|||
|
/// address space.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Reference to an object created using the
|
|||
|
/// RefOf, Index, or CondRefOf operators</remarks>
|
|||
|
public class OperationRegion : AcpiObject
|
|||
|
{
|
|||
|
IOperationRegionAccessor accessor;
|
|||
|
RegionSpace regionSpace;
|
|||
|
ulong startByteIndex;
|
|||
|
ulong numBytes;
|
|||
|
|
|||
|
public OperationRegion(IOperationRegionAccessor accessor,
|
|||
|
RegionSpace regionSpace, ulong startByteIndex, ulong numBytes)
|
|||
|
{
|
|||
|
this.accessor = accessor;
|
|||
|
this.regionSpace = regionSpace;
|
|||
|
this.startByteIndex = startByteIndex;
|
|||
|
this.numBytes = numBytes;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.OperationRegion);
|
|||
|
}
|
|||
|
|
|||
|
public ulong Length
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return numBytes;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// These should only be used by FieldUnit.
|
|||
|
//
|
|||
|
|
|||
|
public byte[] ReadBytes(ulong offset, ulong length)
|
|||
|
{
|
|||
|
if (offset < 0 || offset + length > numBytes) {
|
|||
|
throw new ArgumentOutOfRangeException();
|
|||
|
}
|
|||
|
return accessor.ReadBytes(regionSpace, startByteIndex + offset, length);
|
|||
|
}
|
|||
|
|
|||
|
public byte Read8At(ulong offset)
|
|||
|
{
|
|||
|
if (offset < 0 || offset >= numBytes) {
|
|||
|
throw new ArgumentOutOfRangeException();
|
|||
|
}
|
|||
|
return accessor.Read8(regionSpace, startByteIndex + offset);
|
|||
|
}
|
|||
|
|
|||
|
public uint Read16At(ulong offset)
|
|||
|
{
|
|||
|
if (offset < 0 || offset >= numBytes) {
|
|||
|
throw new ArgumentOutOfRangeException();
|
|||
|
}
|
|||
|
return accessor.Read16(regionSpace, startByteIndex + offset);
|
|||
|
}
|
|||
|
|
|||
|
public uint Read32At(ulong offset)
|
|||
|
{
|
|||
|
if (offset < 0 || offset >= numBytes) {
|
|||
|
throw new ArgumentOutOfRangeException();
|
|||
|
}
|
|||
|
return accessor.Read32(regionSpace, startByteIndex + offset);
|
|||
|
}
|
|||
|
|
|||
|
public void Write8At(ulong offset, byte value)
|
|||
|
{
|
|||
|
if (offset < 0 || offset >= numBytes) {
|
|||
|
throw new ArgumentOutOfRangeException();
|
|||
|
}
|
|||
|
accessor.Write8(regionSpace, startByteIndex + offset, value);
|
|||
|
}
|
|||
|
|
|||
|
public void Write16At(ulong offset, ushort value)
|
|||
|
{
|
|||
|
if (offset < 0 || offset >= numBytes) {
|
|||
|
throw new ArgumentOutOfRangeException();
|
|||
|
}
|
|||
|
accessor.Write16(regionSpace, startByteIndex + offset, value);
|
|||
|
}
|
|||
|
|
|||
|
public void Write32At(ulong offset, uint value)
|
|||
|
{
|
|||
|
if (offset < 0 || offset >= numBytes) {
|
|||
|
throw new ArgumentOutOfRangeException();
|
|||
|
}
|
|||
|
accessor.Write32(regionSpace, startByteIndex + offset, value);
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
// Must first create fields inside operation region and then write to those
|
|||
|
throw new AmlTypeException("Cannot write directly to operation region");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI package object, a fixed-length list of other AcpiObject objects
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Collection of ASL objects with a fixed
|
|||
|
/// number of elements (up to 255).</remarks>
|
|||
|
public class Package : AcpiObject
|
|||
|
{
|
|||
|
AcpiObjectCell[] objectList;
|
|||
|
|
|||
|
public Package(AcpiObjectCell[] objectList)
|
|||
|
{
|
|||
|
this.objectList = objectList;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.Package);
|
|||
|
}
|
|||
|
|
|||
|
public override AcpiObject Index(ulong index)
|
|||
|
{
|
|||
|
return objectList[index].Value;
|
|||
|
}
|
|||
|
|
|||
|
public override AcpiObject[] GetObjects()
|
|||
|
{
|
|||
|
AcpiObject[] result = new AcpiObject[objectList.Length];
|
|||
|
for (ulong index = 0; index < (ulong) objectList.Length; index++) {
|
|||
|
result[index] = this.Index(index);
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException("Cannot write to package object");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI power resource description object.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Power Resource description object</remarks>
|
|||
|
public class PowerResource : AcpiObject
|
|||
|
{
|
|||
|
public byte systemLevel;
|
|||
|
public int resourceOrder;
|
|||
|
|
|||
|
public PowerResource(byte systemLevel, int resourceOrder)
|
|||
|
{
|
|||
|
this.systemLevel = systemLevel;
|
|||
|
this.resourceOrder = resourceOrder;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.PowerResource);
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException("Cannot write to power resource object");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI processor description object.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Processor description object. See
|
|||
|
/// section 17.5.93.</remarks>
|
|||
|
public class Processor : AcpiObject
|
|||
|
{
|
|||
|
byte processorId;
|
|||
|
uint pblkAddress;
|
|||
|
byte pblkLength;
|
|||
|
|
|||
|
public Processor(byte processorId, uint pblkAddress, byte pblkLength)
|
|||
|
{
|
|||
|
this.processorId = processorId;
|
|||
|
this.pblkAddress = pblkAddress;
|
|||
|
this.pblkLength = pblkLength;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.Processor);
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException("Cannot write to processor object");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI string object.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Null-terminated ASCII string.</remarks>
|
|||
|
public class String : AcpiObject
|
|||
|
{
|
|||
|
string contents;
|
|||
|
|
|||
|
public String(string contents)
|
|||
|
{
|
|||
|
for (int i = 0; i < contents.Length; i++) {
|
|||
|
if (contents[i] == '\0') {
|
|||
|
Debug.Assert(false, "ACPI string contains embedded null");
|
|||
|
}
|
|||
|
}
|
|||
|
this.contents = contents;
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.String);
|
|||
|
}
|
|||
|
|
|||
|
public override ulong Size
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return (ulong)contents.Length;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public override AcpiObject Index(ulong index)
|
|||
|
{
|
|||
|
return new Integer(contents[(int)index]);
|
|||
|
}
|
|||
|
|
|||
|
public string Value
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return contents;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public override String GetAsString()
|
|||
|
{
|
|||
|
return this;
|
|||
|
}
|
|||
|
|
|||
|
public override string ToString()
|
|||
|
{
|
|||
|
return contents;
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
this.contents = value.GetAsString().Value;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// An ACPI thermal zone description object.
|
|||
|
/// </summary>
|
|||
|
/// <remarks>From Table 17-6: Thermal Zone description object</remarks>
|
|||
|
public class ThermalZone : AcpiObject
|
|||
|
{
|
|||
|
public ThermalZone()
|
|||
|
{
|
|||
|
// No data - a thermal zone is described entirely by its name and children
|
|||
|
}
|
|||
|
|
|||
|
public override Integer ObjectType()
|
|||
|
{
|
|||
|
return new Integer((ulong)AcpiObjectType.ThermalZone);
|
|||
|
}
|
|||
|
|
|||
|
public override void Write(AcpiObject value)
|
|||
|
{
|
|||
|
throw new AmlTypeException("Cannot write to thermal zone object");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal class AcpiObjectUtils
|
|||
|
{
|
|||
|
public static ulong GetNumBits(ulong value)
|
|||
|
{
|
|||
|
ulong numBits = 0;
|
|||
|
while (value != 0) {
|
|||
|
value >>= 1;
|
|||
|
numBits++;
|
|||
|
}
|
|||
|
return numBits;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|