singrdk/base/Kernel/Singularity.Hal.Acpi/AmlInterpreter/AmlLoader.cs

812 lines
36 KiB
C#
Raw Permalink Normal View History

2008-11-17 18:29:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Microsoft Research Singularity
//
using System;
using System.Collections;
using System.Diagnostics;
using Microsoft.Singularity.Hal.Acpi.AcpiObject;
using Microsoft.Singularity.Hal.Acpi.AmlParserUnions;
using Node = Microsoft.Singularity.Hal.Acpi.AcpiNamespace.Node;
using NodePath = Microsoft.Singularity.Hal.Acpi.AcpiNamespace.NodePath;
using AbsoluteNodePath = Microsoft.Singularity.Hal.Acpi.AcpiNamespace.AbsoluteNodePath;
namespace Microsoft.Singularity.Hal.Acpi
{
public class AmlTypeException : Exception
{
public AmlTypeException() : base("AML type error") { }
public AmlTypeException(string s) : base("AML type error: " + s) { }
}
public class LoadException : Exception
{
public LoadException() : base("Error loading AML") { }
public LoadException(string s) : base("Error loading AML: " + s) { }
}
public class AmlLoader
{
AcpiNamespace acpiNamespace;
AcpiObject.IOperationRegionAccessor operationRegionAccessor;
public AmlLoader(AcpiNamespace acpiNamespace,
AcpiObject.IOperationRegionAccessor operationRegionAccessor)
{
this.acpiNamespace = acpiNamespace;
this.operationRegionAccessor = operationRegionAccessor;
}
public void Load(AmlParser.AMLCode code)
{
// Because of arbitrary forward-references to names in the AML, we
// have to do this in three phases:
// 1. Populate the namespace with all the names;
// 2. Fill in the details of all the object values.
// This allows us to verify that references only reference real
// existing names.
NamesVisitor namesVisitor = new NamesVisitor(acpiNamespace);
foreach (TermObj termObj in code.termList)
{
termObj.Accept(namesVisitor);
}
ValuesVisitor valuesVisitor = new ValuesVisitor(this, acpiNamespace);
foreach (TermObj termObj in code.termList)
{
termObj.Accept(valuesVisitor);
}
}
internal AcpiObject.IOperationRegionAccessor OperationRegionAccessor
{
get
{
return operationRegionAccessor;
}
}
public class NamesVisitor : AmlParserNodeVisitor
{
AcpiNamespace acpiNamespace;
AbsoluteNodePath currentPath;
public NamesVisitor(AcpiNamespace acpiNamespace)
{
this.acpiNamespace = acpiNamespace;
this.currentPath = AbsoluteNodePath.CreateRoot();
}
public override void UnhandledNodeType(string nodeTypeName)
{
throw new LoadException("Encountered unexpected node type " +
nodeTypeName + " at load-time (names phase)");
}
public override void Visit(AmlParser.DefAlias defAlias)
{
acpiNamespace.CreateNodeAt(defAlias.aliasName.nodePath, currentPath);
}
public override void Visit(AmlParser.DefName defName)
{
acpiNamespace.CreateNodeAt(defName.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefScope defScope)
{
AbsoluteNodePath oldPath = currentPath;
currentPath = acpiNamespace.LookupNode(defScope.nameString.nodePath, currentPath).Path;
foreach (TermObj termObj in defScope.termList)
{
termObj.Accept(this);
}
currentPath = oldPath;
}
public override void Visit(AmlParser.DefBankField defBankField)
{
foreach (FieldElement fieldElement in defBankField.fieldList) {
switch (fieldElement.Tag) {
case FieldElement.TagValue.NamedField:
AmlParser.NamedField namedField = fieldElement.GetAsNamedField();
Node node = acpiNamespace.CreateNodeAt(
new NodePath(false/*isAbsolute*/, 0, new string[] { namedField.nameSeg.data }),
currentPath);
break;
default:
break;
}
}
}
public override void Visit(AmlParser.DefCreateBitField defCreateBitField)
{
acpiNamespace.CreateNodeAt(defCreateBitField.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefCreateByteField defCreateByteField)
{
acpiNamespace.CreateNodeAt(defCreateByteField.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefCreateDWordField defCreateDWordField)
{
acpiNamespace.CreateNodeAt(defCreateDWordField.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefCreateField defCreateField)
{
acpiNamespace.CreateNodeAt(defCreateField.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefCreateQWordField defCreateQWordField)
{
acpiNamespace.CreateNodeAt(defCreateQWordField.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefCreateWordField defCreateWordField)
{
acpiNamespace.CreateNodeAt(defCreateWordField.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefDataRegion defDataRegion)
{
acpiNamespace.CreateNodeAt(defDataRegion.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefDevice defDevice)
{
AbsoluteNodePath oldPath = currentPath;
Node node = acpiNamespace.CreateNodeAt(defDevice.nameString.nodePath, currentPath);
currentPath = node.Path;
foreach (AmlObject amlObject in defDevice.amlObjectList)
{
amlObject.Accept(this);
}
currentPath = oldPath;
}
public override void Visit(AmlParser.DefEvent defEvent)
{
acpiNamespace.CreateNodeAt(defEvent.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefField defField)
{
foreach (FieldElement fieldElement in defField.fieldList) {
switch (fieldElement.Tag) {
case FieldElement.TagValue.NamedField:
AmlParser.NamedField namedField = fieldElement.GetAsNamedField();
Node node = acpiNamespace.CreateNodeAt(
new NodePath(false/*isAbsolute*/, 0, new string[] { namedField.nameSeg.data }),
currentPath);
break;
default:
break;
}
}
}
public override void Visit(AmlParser.DefIndexField defIndexField)
{
foreach (FieldElement fieldElement in defIndexField.fieldList) {
switch (fieldElement.Tag) {
case FieldElement.TagValue.NamedField:
AmlParser.NamedField namedField = fieldElement.GetAsNamedField();
Node node = acpiNamespace.CreateNodeAt(
new NodePath(false/*isAbsolute*/, 0, new string[] { namedField.nameSeg.data }),
currentPath);
break;
default:
break;
}
}
}
public override void Visit(AmlParser.DefMethod defMethod)
{
acpiNamespace.CreateNodeAt(defMethod.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefMutex defMutex)
{
acpiNamespace.CreateNodeAt(defMutex.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefOpRegion defOpRegion)
{
acpiNamespace.CreateNodeAt(defOpRegion.nameString.nodePath, currentPath);
}
public override void Visit(AmlParser.DefPowerRes defPowerRes)
{
AbsoluteNodePath oldPath = currentPath;
Node node = acpiNamespace.CreateNodeAt(defPowerRes.nameString.nodePath, currentPath);
currentPath = node.Path;
foreach (AmlObject amlObject in defPowerRes.amlObjectList)
{
amlObject.Accept(this);
}
currentPath = oldPath;
}
public override void Visit(AmlParser.DefProcessor defProcessor)
{
AbsoluteNodePath oldPath = currentPath;
Node node = acpiNamespace.CreateNodeAt(defProcessor.nameString.nodePath, currentPath);
currentPath = node.Path;
foreach (AmlObject amlObject in defProcessor.amlObjectList)
{
amlObject.Accept(this);
}
currentPath = oldPath;
}
public override void Visit(AmlParser.DefThermalZone defThermalZone)
{
AbsoluteNodePath oldPath = currentPath;
Node node = acpiNamespace.CreateNodeAt(defThermalZone.nameString.nodePath, currentPath);
currentPath = node.Path;
foreach (AmlObject amlObject in defThermalZone.amlObjectList)
{
amlObject.Accept(this);
}
currentPath = oldPath;
}
public override void Visit(AmlParser.DefIfElse defIfElse)
{
//
// Load-time Ifs are both rare and tricky, because it makes the
// two-phase model here unworkable: we can't let the NamesVisitor
// visit the if body before the truth value of its predicate is
// known, but this may depend on values filled in by the ValuesVisitor.
// Being an exceptional case, we just have the NamesVisitor always
// visit both branches, which works for the examples I've come across
// like the AMD with Infineon TPM.
//
foreach (TermObj termObj in defIfElse.termList) {
termObj.Accept(this);
}
if (defIfElse.defElse.termList != null) {
foreach (TermObj termObj in defIfElse.defElse.termList) {
termObj.Accept(this);
}
}
}
}
public class ValuesVisitor : AmlParserNodeVisitor
{
AcpiNamespace acpiNamespace;
AmlLoader loader;
AbsoluteNodePath currentPath;
public ValuesVisitor(AmlLoader loader, AcpiNamespace acpiNamespace)
{
this.acpiNamespace = acpiNamespace;
this.currentPath = AbsoluteNodePath.CreateRoot();
this.loader = loader;
}
public override void UnhandledNodeType(string nodeTypeName)
{
throw new LoadException("Encountered unexpected node type " +
nodeTypeName + " at load-time (values phase)");
}
public override void Visit(AmlParser.DefAlias defAlias)
{
Node sourceNode = acpiNamespace.LookupNode(defAlias.sourceName.nodePath, currentPath);
Node aliasNode = acpiNamespace.LookupNode(defAlias.aliasName.nodePath, currentPath);
aliasNode.AliasTo(sourceNode);
}
public override void Visit(AmlParser.DefName defName)
{
Node node = acpiNamespace.LookupNode(defName.nameString.nodePath, currentPath);
node.Value = LoadTimeEvaluate(defName.dataRefObject);
}
public override void Visit(AmlParser.DefScope defScope)
{
AbsoluteNodePath oldPath = currentPath;
currentPath = acpiNamespace.LookupNode(defScope.nameString.nodePath, currentPath).Path;
foreach (TermObj termObj in defScope.termList)
{
termObj.Accept(this);
}
currentPath = oldPath;
}
public override void Visit(AmlParser.DefBankField defBankField)
{
Node operationRegionNode = acpiNamespace.LookupNode(defBankField.regionName.nodePath, currentPath);
CheckObjectType(operationRegionNode.Value, AcpiObjectType.OperationRegion);
// TODO: BankFields are not used in the test files and appear to involve some kind of
// "bank selection register". Need to understand this properly to implement it, but for
// leaving unimplemented. Commented out below is some code to use as a starting point.
throw new LoadException("BankField unimplemented");
#if false
AccessType accessType = defBankField.fieldFlags.accessType;
AccessAttrib accessAttrib = AccessAttrib.SMBNone;
int bitIndex = 0;
foreach (FieldElement fieldElement in defBankField.fieldList) {
switch (fieldElement.Tag) {
case FieldElement.TagValue.NamedField:
AmlParser.NamedField namedField = fieldElement.GetAsNamedField();
Node node = acpiNamespace.LookupNode(
new NodePath(false/*isAbsolute*/, 0, new string[] { namedField.nameSeg.data }),
currentPath);
node.Value = new FieldUnit((AcpiObject.OperationRegion)operationRegionNode.Value,
bitIndex, namedField.bitWidth,
accessType, accessAttrib,
defBankField.fieldFlags.lockRule,
defBankField.fieldFlags.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'");
}
}
#endif
}
public override void Visit(AmlParser.DefCreateBitField defCreateBitField)
{
VisitField(defCreateBitField.sourceBuff,
defCreateBitField.bitIndex.integer, 1, 1/*numBits*/,
defCreateBitField.nameString.nodePath);
}
public override void Visit(AmlParser.DefCreateByteField defCreateByteField)
{
VisitField(defCreateByteField.sourceBuff,
defCreateByteField.byteIndex.integer, 8, 8/*numBits*/,
defCreateByteField.nameString.nodePath);
}
public override void Visit(AmlParser.DefCreateDWordField defCreateDWordField)
{
VisitField(defCreateDWordField.sourceBuff,
defCreateDWordField.byteIndex.integer, 8, 32/*numBits*/,
defCreateDWordField.nameString.nodePath);
}
public override void Visit(AmlParser.DefCreateField defCreateField)
{
AcpiObject.AcpiObject sizeObj = LoadTimeEvaluate(defCreateField.numBits.integer);
CheckObjectType(sizeObj, AcpiObjectType.Integer);
VisitField(defCreateField.sourceBuff,
defCreateField.bitIndex.integer, 1,
((AcpiObject.Integer)(sizeObj.GetTarget())).Value,
defCreateField.nameString.nodePath);
}
public override void Visit(AmlParser.DefCreateQWordField defCreateQWordField)
{
VisitField(defCreateQWordField.sourceBuff,
defCreateQWordField.byteIndex.integer, 8, 64/*numBits*/,
defCreateQWordField.nameString.nodePath);
}
public override void Visit(AmlParser.DefCreateWordField defCreateWordField)
{
VisitField(defCreateWordField.sourceBuff,
defCreateWordField.byteIndex.integer, 8, 16/*numBits*/,
defCreateWordField.nameString.nodePath);
}
public void VisitField(AmlParser.SourceBuff sourceBuff,
TermArg indexTermArg, ulong bitIndexMultiplier,
ulong bitSize,
NodePath fieldName)
{
AcpiObject.AcpiObject indexObj = LoadTimeEvaluate(indexTermArg);
CheckObjectType(indexObj, AcpiObjectType.Integer);
ulong index = ((AcpiObject.Integer)(indexObj.GetTarget())).Value;
ulong bitIndex = index * bitIndexMultiplier;
AcpiObject.AcpiObject bufferObj = LoadTimeEvaluate(sourceBuff.buffer);
CheckObjectType(bufferObj, AcpiObjectType.Buffer);
Node node = acpiNamespace.LookupNode(fieldName, currentPath);
node.Value = new BufferField((AcpiObject.Buffer)(bufferObj.GetTarget()), bitIndex, bitSize);
}
public override void Visit(AmlParser.DefDataRegion defDataRegion)
{
// TODO: This method will have to go back to the XSDT table
// to look up the designated table and its location so that
// it can produce a corresponding AcpiObject.OperationRegion.
// It is not used in the three test DDBs.
throw new LoadException("TODO Not yet implemented");
}
public override void Visit(AmlParser.DefDevice defDevice)
{
AbsoluteNodePath oldPath = currentPath;
Node node = acpiNamespace.LookupNode(defDevice.nameString.nodePath, currentPath);
string[] segments = new string[currentPath.NameSegments.Length
+ defDevice.nameString.nodePath.NameSegments.Length];
int index = 0;
foreach (string segment in currentPath.NameSegments)
{
segments[index++] = segment;
}
foreach (string segment in defDevice.nameString.nodePath.NameSegments)
{
segments[index++] = segment;
}
AbsoluteNodePath devPath = new AbsoluteNodePath(segments);
node.Value = new AcpiObject.Device(devPath);
currentPath = node.Path;
foreach (AmlObject amlObject in defDevice.amlObjectList)
{
amlObject.Accept(this);
}
currentPath = oldPath;
}
public override void Visit(AmlParser.DefEvent defEvent)
{
Node node = acpiNamespace.LookupNode(defEvent.nameString.nodePath, currentPath);
node.Value = new AcpiObject.Event();
}
public override void Visit(AmlParser.DefField defField)
{
Node operationRegionNode = acpiNamespace.LookupNode(defField.nameString.nodePath, currentPath);
CheckObjectType(operationRegionNode.Value, AcpiObjectType.OperationRegion);
SortedList fields = FieldUnit.CreateFromFieldList((AcpiObject.OperationRegion)(operationRegionNode.Value.GetTarget()),
defField.fieldList,
defField.fieldFlags.accessType, AccessAttrib.SMBNone,
defField.fieldFlags.lockRule, defField.fieldFlags.updateRule);
foreach (DictionaryEntry entry in fields) {
Node node = acpiNamespace.LookupNode(
new NodePath(false/*isAbsolute*/, 0, new string[] { (string)entry.Key }),
currentPath);
node.Value = (FieldUnit)entry.Value;
}
}
public override void Visit(AmlParser.DefIndexField defIndexField)
{
Node indexNode = acpiNamespace.LookupNode(defIndexField.indexName.nodePath, currentPath);
CheckObjectType(indexNode.Value, AcpiObjectType.FieldUnit);
AcpiObject.FieldUnit indexField = (AcpiObject.FieldUnit)(indexNode.Value.GetTarget());
Node dataNode = acpiNamespace.LookupNode(defIndexField.dataName.nodePath, currentPath);
CheckObjectType(dataNode.Value, AcpiObjectType.FieldUnit);
AcpiObject.FieldUnit dataField = (AcpiObject.FieldUnit)(dataNode.Value.GetTarget());
OperationRegion indexFieldRegion =
new OperationRegion(new IndexFieldOperationRegionAccessor(indexField, dataField),
RegionSpace.SystemIO/*unused*/, 0, 256/*index field never exceeds 8 bits*/);
AccessType accessType = defIndexField.fieldFlags.accessType;
AccessAttrib accessAttrib = AccessAttrib.SMBNone;
int bitIndex = 0;
foreach (FieldElement fieldElement in defIndexField.fieldList) {
switch (fieldElement.Tag) {
case FieldElement.TagValue.NamedField:
AmlParser.NamedField namedField = fieldElement.GetAsNamedField();
Node node = acpiNamespace.LookupNode(
new NodePath(false/*isAbsolute*/, 0, new string[] { namedField.nameSeg.data }),
currentPath);
node.Value = new FieldUnit(indexFieldRegion, bitIndex, namedField.bitWidth,
accessType, accessAttrib,
defIndexField.fieldFlags.lockRule,
defIndexField.fieldFlags.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'");
}
}
}
public override void Visit(AmlParser.DefMethod defMethod)
{
Node node = acpiNamespace.LookupNode(defMethod.nameString.nodePath, currentPath);
node.Value = new AcpiObject.BytecodeMethod(defMethod.methodFlags.argCount,
defMethod.methodFlags.serializeFlag,
defMethod.methodFlags.syncLevel,
defMethod.unparsedTermList);
}
public override void Visit(AmlParser.DefMutex defMutex)
{
Node node = acpiNamespace.LookupNode(defMutex.nameString.nodePath, currentPath);
node.Value = new AcpiObject.Mutex(defMutex.syncFlags.syncLevel);
}
public override void Visit(AmlParser.DefOpRegion defOpRegion)
{
AcpiObject.AcpiObject startIndexObj = LoadTimeEvaluate(defOpRegion.regionOffset.integer);
AcpiObject.AcpiObject lengthObj = LoadTimeEvaluate(defOpRegion.regionLen.integer);
CheckObjectType(lengthObj, AcpiObjectType.Integer);
Node node = acpiNamespace.LookupNode(defOpRegion.nameString.nodePath, currentPath);
node.Value = new AcpiObject.OperationRegion(loader.OperationRegionAccessor,
(RegionSpace)defOpRegion.regionSpace.byteData,
startIndexObj.GetAsInt().Value,
((AcpiObject.Integer)(lengthObj.GetTarget())).Value);
}
public override void Visit(AmlParser.DefPowerRes defPowerRes)
{
AbsoluteNodePath oldPath = currentPath;
Node node = acpiNamespace.LookupNode(defPowerRes.nameString.nodePath, currentPath);
node.Value = new AcpiObject.PowerResource(defPowerRes.systemLevel.byteData,
defPowerRes.resourceOrder.wordData);
currentPath = node.Path;
foreach (AmlObject amlObject in defPowerRes.amlObjectList)
{
amlObject.Accept(this);
}
currentPath = oldPath;
}
public override void Visit(AmlParser.DefProcessor defProcessor)
{
AbsoluteNodePath oldPath = currentPath;
Node node = acpiNamespace.LookupNode(defProcessor.nameString.nodePath, currentPath);
node.Value = new AcpiObject.Processor(defProcessor.procID.byteData,
defProcessor.pblkAddr.dWordData,
defProcessor.pblkLen.byteData);
currentPath = node.Path;
foreach (AmlObject amlObject in defProcessor.amlObjectList)
{
amlObject.Accept(this);
}
currentPath = oldPath;
}
public override void Visit(AmlParser.DefThermalZone defThermalZone)
{
AbsoluteNodePath oldPath = currentPath;
Node node = acpiNamespace.LookupNode(defThermalZone.nameString.nodePath, currentPath);
node.Value = new AcpiObject.ThermalZone();
currentPath = node.Path;
foreach (AmlObject amlObject in defThermalZone.amlObjectList)
{
amlObject.Accept(this);
}
currentPath = oldPath;
}
private AcpiObject.AcpiObject LoadTimeEvaluate(AmlParserNode parserNode)
{
LoadTimeEvaluateVisitor visitor =
new LoadTimeEvaluateVisitor(acpiNamespace, currentPath);
parserNode.Accept(visitor);
return visitor.Result;
}
public override void Visit(AmlParser.DefIfElse defIfElse)
{
LoadTimeEvaluateVisitor visitor =
new LoadTimeEvaluateVisitor(acpiNamespace, currentPath);
defIfElse.predicate.integer.Accept(visitor);
if (visitor.Result.GetAsInt().Value != 0) {
foreach (TermObj termObj in defIfElse.termList) {
termObj.Accept(this);
}
}
else if (defIfElse.defElse.termList != null) {
foreach (TermObj termObj in defIfElse.defElse.termList) {
termObj.Accept(this);
}
}
}
}
public class LoadTimeEvaluateVisitor : AmlParserNodeVisitor
{
AcpiNamespace acpiNamespace;
AbsoluteNodePath currentPath;
public LoadTimeEvaluateVisitor(AcpiNamespace acpiNamespace, AbsoluteNodePath currentPath)
{
this.acpiNamespace = acpiNamespace;
this.currentPath = currentPath;
}
public override void UnhandledNodeType(string nodeTypeName)
{
throw new LoadException("Encountered unexpected node type " +
nodeTypeName + " at load-time (during evaluation)");
}
private AcpiObject.AcpiObject result;
public AcpiObject.AcpiObject Result
{
get
{
return result;
}
}
public override void Visit(AmlParser.DefPackage defPackage)
{
VisitPackage(defPackage.numElements.byteData,
defPackage.packageElementList);
}
public override void Visit(AmlParser.DefVarPackage defVarPackage)
{
defVarPackage.varNumElements.integer.Accept(this);
AcpiObject.AcpiObject numElementsObj = result;
CheckObjectType(numElementsObj, AcpiObjectType.Integer);
VisitPackage((byte)(((AcpiObject.Integer)(numElementsObj.GetTarget())).Value),
defVarPackage.packageElementList);
}
private void VisitPackage(byte numElements, PackageElement[] packageElementList)
{
AcpiObjectCell[] elements = new AcpiObjectCell[numElements];
for(int i = 0; i < elements.Length; i++) {
if (i < packageElementList.Length) {
packageElementList[i].Accept(this);
elements[i] = new AcpiObjectCell(result);
}
else {
elements[i] = new AcpiObjectCell(new AcpiObject.UninitializedObject());
}
}
result = new AcpiObject.Package(elements);
}
public override void Visit(ComputationalData computationalData)
{
switch (computationalData.Tag) {
case ComputationalData.TagValue.ByteConst:
result = new AcpiObject.Integer(computationalData.GetAsByteConst());
break;
case ComputationalData.TagValue.WordConst:
result = new AcpiObject.Integer(computationalData.GetAsWordConst());
break;
case ComputationalData.TagValue.DWordConst:
result = new AcpiObject.Integer(computationalData.GetAsDWordConst());
break;
case ComputationalData.TagValue.QWordConst:
result = new AcpiObject.Integer(computationalData.GetAsQWordConst());
break;
case ComputationalData.TagValue.StringConst:
result = new AcpiObject.String(computationalData.GetAsStringConst());
break;
case ComputationalData.TagValue.RevisionOp:
result = AcpiObject.IntegerConstant.Revision.GetAsInt();
break;
default:
base.Visit(computationalData);
break;
}
}
public override void Visit(AmlParser.ConstObj constObj)
{
if (constObj.op == AmlParser.ZeroOp) {
result = AcpiObject.IntegerConstant.Zero.GetAsInt();
}
else if (constObj.op == AmlParser.OneOp) {
result = AcpiObject.IntegerConstant.One.GetAsInt();
}
else if (constObj.op == AmlParser.OnesOp) {
result = AcpiObject.IntegerConstant.Ones.GetAsInt();
}
}
public override void Visit(AmlParser.DefBuffer defBuffer)
{
defBuffer.bufferSize.integer.Accept(this);
AcpiObject.AcpiObject bufferSizeObj = result;
CheckObjectType(bufferSizeObj, AcpiObjectType.Integer);
byte[] contents = new byte[((AcpiObject.Integer)(bufferSizeObj.GetTarget())).Value];
Array.Copy(defBuffer.byteList, contents, defBuffer.byteList.Length);
result = new AcpiObject.Buffer(contents);
}
public override void Visit(AmlParser.UserTermObj userTermObj)
{
// At load time, it can't have any args, so just look it up in the namespace.
// Note that we can't simply copy the value from the given node, for two reasons:
//
// 1. UserTermObj references can be forwards or backwards, or even circular, as shown
// in this example:
// Name (BAR0, Package (0x1) { BAR1 })
// Name (BAR1, Package (0x1) { BAR0 })
// 2. Although the spec doesn't clarify this, I believe a UserTermObj is intended to be
// aliased to the named node so that later changes to it are reflected in the object
// containing the reference.
//
// To deal with we have a special "fake" object type containing an absolute NodePath that
// acts as a direct reference to an object (not the sort handled by AcpiObject.ObjectReference,
// which are different). An alternative would be to attempt to use the same aliasing of nodes
// used by DefAlias, but this would be painful and make it later indistinguishable who is the
// alias and who the original definition, which might be important.
result = new AcpiObject.NodePathReference(acpiNamespace,
acpiNamespace.LookupNode(userTermObj.nameString.nodePath, currentPath).Path);
}
public override void Visit(AmlParser.ObjReference objReference)
{
objReference.termArg.Accept(this);
}
}
private static void CheckObjectType(AcpiObject.AcpiObject obj, AcpiObjectType type)
{
if (obj.ObjectType().Value != (ulong)type) {
throw new AmlTypeException();
}
}
}
}