singrdk/base/Kernel/Singularity.Hal.Acpi/AcpiTables.cs

271 lines
8.7 KiB
C#

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: AcpiTables.cs
//
// Note:
// Based on ACPI 3.0 Spec.
namespace Microsoft.Singularity.Hal.Acpi
{
using System;
using Microsoft.Singularity.Io;
[ CLSCompliant(false) ]
internal class AcpiTables
{
private static Fadt fadt;
private static Madt madt;
private static Dsdt dsdt;
private static Ssdt ssdt;
private static Srat srat;
private static PMTimer pmTimer;
private static UIntPtr GetRsdpBase()
{
unsafe
{
return BootInfo.GetBootInfo().AcpiRoot32;
}
}
public static Fadt GetFadt()
{
return fadt;
}
public static Madt GetMadt()
{
return madt;
}
public static Srat GetSrat()
{
return srat;
}
public static PMTimer GetPMTimer()
{
return pmTimer;
}
public static void Parse()
{
UIntPtr rsdpBase = GetRsdpBase();
if (rsdpBase == UIntPtr.Zero) {
DebugStub.Print("ACPI RSDP not found\n");
}
DebugStub.Print("ACPI RSDP address is {0:x8}\n",
__arglist(rsdpBase));
Rsdp rsdp = Rsdp.Parse(rsdpBase, 36u);
DebugStub.Print("ACPI RSDP OemId is {0:x8}\n",
__arglist(rsdp.OemId));
DebugStub.Print("ACPI RSDP revision is {0:x8}\n",
__arglist(rsdp.Revision));
DebugStub.Print("ACPI RSDT address is {0:x8}\n",
__arglist(rsdp.RsdtAddress));
SystemTableHeader rsdtHeader =
SystemTableHeader.Create(rsdp.RsdtAddress);
Rsdt rsdt = Rsdt.Create(rsdtHeader);
DebugStub.Print("RSDT contains:\n");
for (int i = 0; i < rsdt.EntryCount; i++) {
SystemTableHeader header = rsdt.GetTableHeader(i);
DebugStub.Print(" {0:x8}\n", __arglist(header.Signature));
if (header.Signature == Fadt.Signature) {
fadt = Fadt.Create(header);
}
else if (header.Signature == Madt.Signature) {
madt = Madt.Create(header);
}
else if (header.Signature == Ssdt.Signature) {
ssdt = Ssdt.Create(header);
}
// haryadi - Srat, Slit
else if (header.Signature == Srat.Signature)
{
srat = Srat.Create(header);
srat.ParseSratStructure();
// srat.DumpSratOffsets();
// srat.DumpSratImportantFields();
// srat.DumpSratStructure();
}
}
if (fadt != null) {
pmTimer = PMTimer.Create(fadt);
DebugStub.Print("PMTimer Value={0} Width={1}\n",
__arglist(pmTimer.Value, pmTimer.Width));
uint t0 = pmTimer.Value;
uint t1 = pmTimer.Value;
uint t2 = pmTimer.Value;
uint delta = (t2 >= t1) ? t2 - t1 : ((t1 | 0xff000000) - t2);
DebugStub.Print("Read cost {0} ticks\n", __arglist(delta));
if (fadt.DSDT != 0)
{
dsdt = Dsdt.Create(
SystemTableHeader.Create(fadt.DSDT)
);
}
}
if (dsdt != null) {
DumpRegion("DSDT", dsdt.Region);
}
if (ssdt != null) {
DumpRegion("SSDT", ssdt.Region);
}
}
private static char Hex(int v)
{
if (v < 10) {
return (char)('0' + v);
}
else {
return (char)('A' + v - 10);
}
}
private static void DumpRegion(string name, IoMemory region)
{
#if FALSE
// (new NamespaceWalker(region)).Display();
DebugStub.Print("-----------------------------------------------------------------------------\n");
DebugStub.Print("Table {0} dump\n", __arglist(name));
DebugStub.Print("-----------------------------------------------------------------------------\n");
const int step = 16;
byte last = region.Read8(0);
for (int i = 0; i < region.Length - 8; i ++) {
if (region.Read8(i + 0) == (byte)'_' &&
(region.Read8(i + 1) == (byte)'C' ||
region.Read8(i + 1) == (byte)'H') &&
region.Read8(i + 2) == (byte)'I' &&
region.Read8(i + 3) == (byte)'D') {
int o = 1;
byte d0 = region.Read8(i + 4 + o);
byte d1 = region.Read8(i + 5 + o);
byte d2 = region.Read8(i + 6 + o);
byte d3 = region.Read8(i + 7 + o);
char c0 = (char)(((d0 & 0x7f) >> 2) + 0x40);
char c1 = (char)((((d0 & 0x3) << 3) | (d1 >> 5)) + 0x40);
char c2 = (char)((d1 & 0x1f) + 0x40);
char c3 = Hex(d2 >> 4);
char c4 = Hex(d2 & 0xf);
char c5 = Hex(d3 >> 4);
char c6 = Hex(d3 & 0xf);
DebugStub.Print("{0:x8} -> _{8}ID {1}{2}{3}{4}{5}{6}{7}\n",
__arglist(i, c0, c1, c2,
c3, c4, c5, c6,
(char)region.Read8(i + 1)));
}
}
for (int i = 0; i < region.Length; i += step) {
DebugStub.Print("{0:x8} : ", __arglist(i));
int n = step;
if (region.Length - i < n) {
n = region.Length - i;
}
for (int j = 0; j < n; j++) {
char c = (char)region.Read8(i + j);
DebugStub.Print("{0:x2} ", __arglist((int)c));
}
for (int j = 0; j < n; j++) {
char c = (char)region.Read8(i + j);
if (c < 32 || c > 127)
c = '.';
DebugStub.Print(c.ToString());
}
DebugStub.Print("\n");
}
DebugStub.Print("\n");
#endif // FALSE
}
internal class NamespaceWalker
{
int cursor = 0;
IoMemory memory;
internal NamespaceWalker(IoMemory m)
{
this.memory = m;
}
byte Read8()
{
return this.memory.Read8(cursor++);
}
ushort Read16()
{
ushort r = this.memory.Read16(cursor);
cursor += 2;
return r;
}
uint Read32()
{
uint r = this.memory.Read32(cursor++);
cursor += 4;
return r;
}
int GetPackageLength()
{
byte b = Read8();
int length = (int)b & 0x3f;
int following = ((int)b & 0xc) >> 6;
while (following-- > 0) {
length = length << 8;
length += (int)Read8();
}
return length;
}
void Reset()
{
cursor = 0;
}
internal void Display()
{
while (cursor < this.memory.Length) {
DisplayPackage(0);
}
}
void DisplayPackage(int depth)
{
int length = GetPackageLength();
int oldCursor = this.cursor;
DebugStub.Print("Package Length {0} Name {1}{2}{3}{4}",
__arglist(length,
(char)Read8(),
(char)Read8(),
(char)Read8(),
(char)Read8()));
cursor = oldCursor + length;
}
}
}
}