internal ACPIObject EvaluateTo(DataType dest_type, IMachineInterface mi, Namespace.State s, Namespace n) { if (this.Type == dest_type) { return(this); } /* First evaluate fields methods etc */ ACPIObject ret = Evaluate(mi, s, n); return(ConvertTo(ret, dest_type)); }
public ICollection <File.Property> GetCurrentResources(string crs_object) { Aml.ACPIObject crs = EvaluateObject(crs_object); if (crs == null) { return new File.Property[] { } } ; if (crs.Type != Aml.ACPIObject.DataType.Buffer) { return new File.Property[] { } } ; List <File.Property> ret = new List <File.Property>(); acpi.InterpretResources(crs, ret); return(ret); }
public Aml.ACPIObject EvaluateObject(string name, IList <Aml.ACPIObject> args, Aml.ACPIObject.DataType to_type) { ACPIName valid_name = GetValidName(name); Aml.ACPIObject ret = acpi.n.Evaluate(valid_name, acpi.mi, GetArguments(args)); if (ret == null) { return(null); } Namespace.State s = new Namespace.State { Args = new Dictionary <int, ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()), Locals = new Dictionary <int, ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()), Scope = acpi.n.FindObject(name).Name }; return(ret.EvaluateTo(to_type, acpi.mi, s, acpi.n)); }
internal override ACPIObject Execute(Namespace.State state) { ACPIObject osval = state.Args[0].EvaluateTo(ACPIObject.DataType.String, _mi, state, _n); string osvalstr = osval.Data as string; if (osvalstr == null) { System.Diagnostics.Debugger.Log(0, "acpipc", "_OSI(null) called, returning 0"); return(Namespace.Zero); } ulong ret = Namespace.Zero; if (osvalstr == "Windows 2015") { ret = Namespace.Ones; } System.Diagnostics.Debugger.Log(0, "acpipc", "_OSI(" + osvalstr + ") called, returning " + ret.ToString()); return(ret); }
public static ACPIObject ReadIndexField(ACPIObject.IndexFieldUnitData ifd, IMachineInterface mi, Namespace.State s, Namespace n) { ACPIObject data = ifd.Data.EvaluateTo(ACPIObject.DataType.FieldUnit, mi, s, n); ACPIObject index = ifd.Index.EvaluateTo(ACPIObject.DataType.FieldUnit, mi, s, n); if (ifd.BitOffset % 8 != 0) { throw new NotImplementedException(); } if (ifd.BitLength % 8 != 0) { throw new NotImplementedException(); } ulong byte_offset = (ulong)(ifd.BitOffset / 8); WriteField(byte_offset, index.Data as ACPIObject.FieldUnitData, mi); ACPIObject res = ReadField(data.Data as ACPIObject.FieldUnitData, mi); return(res); }
public static void WriteField(ACPIObject val, ACPIObject.FieldUnitData fd, IMachineInterface mi) { ACPIObject.OpRegionData oprd = fd.OpRegion.Data as ACPIObject.OpRegionData; ulong addr = oprd.Offset; if ((fd.BitOffset % 8) != 0) { throw new NotImplementedException(); } addr += (ulong)(fd.BitOffset / 8); ulong mask = 0xffffffffffffffff; int alength = 0; switch (fd.Access) { case ACPIObject.FieldUnitData.AccessType.ByteAcc: alength = 8; break; case ACPIObject.FieldUnitData.AccessType.WordAcc: alength = 16; break; case ACPIObject.FieldUnitData.AccessType.DWordAcc: alength = 32; break; case ACPIObject.FieldUnitData.AccessType.QWordAcc: alength = 64; break; case ACPIObject.FieldUnitData.AccessType.AnyAcc: alength = fd.BitLength; break; } if (alength <= 8) { alength = 8; } else if (alength <= 16) { alength = 16; } else if (alength <= 32) { alength = 32; } else if (alength <= 64) { alength = 64; } else { throw new Exception("Unsupported access length: " + alength.ToString()); } switch (oprd.RegionSpace) { case 0: // SystemMemory switch (alength) { case 8: mi.WriteMemoryByte(addr, (byte)val); break; case 16: mi.WriteMemoryWord(addr, (ushort)val); break; case 32: mi.WriteMemoryDWord(addr, (uint)val); break; case 64: mi.WriteMemoryQWord(addr, val); break; } break; case 1: // SystemIO switch (alength) { case 8: mi.WriteIOByte(addr, (byte)val); break; case 16: mi.WriteIOWord(addr, (ushort)val); break; case 32: mi.WriteIODWord(addr, (uint)val); break; case 64: mi.WriteIOQWord(addr, val); break; } break; default: throw new NotImplementedException(); } }
private void AddDevice(IEnumerable <string> hid_strs, string name, Aml.ACPIObject obj, Aml.Namespace n, Aml.IMachineInterface mi) { StringBuilder sb = new StringBuilder(); int cnt = 0; foreach (var hid_str in hid_strs) { if (cnt != 0) { sb.Append(", "); } sb.Append(hid_str); cnt++; } System.Diagnostics.Debugger.Log(0, "acpipc", name + ": " + sb.ToString()); /* This is a mapping of PNP IDs/ACPI IDs to tysos device driver names */ string tysos_driver = "unknown"; string tysos_subdriver = null; foreach (var hid_str in hid_strs) { if (hid_str == "0A0CD041") { // PNP0C0A ACPI control method battery tysos_driver = "acpipc"; tysos_subdriver = "bat"; } else if (hid_str == "030AD041") { // PNP0A03 PCI bus tysos_driver = "pci"; tysos_subdriver = "hostbridge"; } else if (hid_str == "0001D041") { // PNP0100 AT system timer tysos_driver = "isa"; tysos_subdriver = "pit"; } else if (hid_str == "0F0CD041") { // PNP0C0F PCI interrupt link device tysos_driver = null; /* Dump its IRQ linkage */ Aml.ACPIObject lnk_res = n.Evaluate(name + "._CRS", mi); if (lnk_res != null) { List <File.Property> lnk_props = new List <File.Property>(); InterpretResources(lnk_res, lnk_props); foreach (var lnk_prop in lnk_props) { if (lnk_prop.Name == "interrupt") { System.Diagnostics.Debugger.Log(0, "acpipc", name + " -> " + lnk_prop.Value.ToString()); } } } } else if (hid_str == "ACPI0003") { // ACPI0003 ACPI Power source device tysos_driver = "acpipc"; tysos_subdriver = "power"; } else if (hid_str == "0301D041") { // PNP0103 HPET tysos_driver = "hpet"; } else if (hid_str == "0303D041") { // PNP0303 IBM enhanced keyboard (101/102-key, PS/2 mouse support) tysos_driver = "ps2"; } else if (hid_str == "030FD041") { // PNP0F03 Microsoft PS/2-style Mouse tysos_driver = "ps2"; } else if (hid_str == "0000D041") { // PNP0000 AT programmable interrupt controller tysos_driver = null; } else if (hid_str == "000BD041") { // PNP0B00 AT real-time clock tysos_driver = "isa"; tysos_subdriver = "rtc"; } else if (hid_str == "0105D041") { // PNP0501 16550A-compatible COM port tysos_driver = "isa"; tysos_subdriver = "serial"; } else if (hid_str == "0007D041") { // PNP0700 PC standard floppy disk controller tysos_driver = "fdc"; } else if (name == "0004D041") { // PNP0400 Standard LPT printer port tysos_driver = "isa"; tysos_subdriver = "lpt"; } else if (hid_str == "0002D041") { // PNP0200 AT DMA controller tysos_driver = "isa"; tysos_subdriver = "dma"; } else if (hid_str == "cpu" || hid_str == "ACPI0007") { // ACPI cpu object tysos_driver = "x86_64-cpu"; } if (tysos_driver == null) { return; } if (tysos_driver != "unknown") { break; } } /* Populate the device nodes properties */ List <tysos.lib.File.Property> props = new List <tysos.lib.File.Property>(); props.Add(new tysos.lib.File.Property { Name = "driver", Value = tysos_driver }); foreach (var hid_str in hid_strs) { props.Add(new tysos.lib.File.Property { Name = "acpiid", Value = hid_str }); } props.Add(new tysos.lib.File.Property { Name = "acpiname", Value = name }); ACPIConfiguration dev_conf = new ACPIConfiguration(this, name); props.Add(new tysos.lib.File.Property { Name = "acpiconf", Value = dev_conf }); /* Add PCI specific information */ if (tysos_driver == "pci") { /* Pass PCI IRQ routing information */ foreach (var lnk in lnks) { ACPIConfiguration lnk_conf = new ACPIConfiguration(this, lnk); props.Add(new File.Property { Name = "acpiconf", Value = lnk_conf }); } /* Pass unassigned ISA IRQs */ foreach (var isa_irq in isa_irqs) { if (isa_irq != null && isa_irq.irq != -1) { props.Add(new File.Property { Name = "interrupt", Value = isa_irq }); } } /* Pass a reasonable chunk of the address space */ var vmem = vmems.Alloc(0x1000000000UL, 0x1000UL); if (vmem != null) { props.Add(new File.Property { Name = "vmem", Value = vmem }); } } /* Add CPU specific information */ if (tysos_driver == "x86_64-cpu") { /* See ACPI 8.4 * Get the ACPI ID of the processor so we can match this * with a processor in the MADT table. This may be in two * forms: It can be a _UID object under the processor object, * or can be a field of the Processor object */ Aml.ACPIObject uid = n.Evaluate(name + "._UID", mi); bool found = false; bool enabled = true; if (uid != null && uid.Type == ACPIObject.DataType.Integer) { uint uid_val = (uint)uid.IntegerData; /* LAPIC structures don't contain UIDs and we don't * support Local SAPICs or Local x2APICs yet */ props.Add(new File.Property { Name = "acpiuid", Value = uid_val }); } if (found == false && obj.Type == ACPIObject.DataType.Processor) { /* Try parsing using ACPI ID instead */ var pd = obj.Data as ACPIObject.ProcessorData; foreach (var lapic in lapics) { if (lapic.ACPIProcessorID == pd.ID) { if ((lapic.Flags & 0x1) == 0) { enabled = false; } props.Add(new File.Property { Name = "apicid", Value = lapic.APICID }); tysos_subdriver = "lapic"; found = true; break; } } } if (found == false || enabled == false) { return; } if (obj.Type == ACPIObject.DataType.Processor) { var pd = obj.Data as ACPIObject.ProcessorData; props.Add(new File.Property { Name = "acpiprocid", Value = pd.ID }); if (pd.BlkLen != 0) { props.Add(new File.Property { Name = "io", Value = ios.AllocFixed(pd.BlkAddr, pd.BlkLen, true) }); } } } /* Get resources owned by the device */ Aml.ACPIObject resources = n.Evaluate(name + "._CRS", mi); if (resources != null) { InterpretResources(resources, props); } /* Generate a unique name for the device */ if (tysos_subdriver != null) { props.Add(new tysos.lib.File.Property { Name = "subdriver", Value = tysos_subdriver }); } int dev_no = 0; sb = new StringBuilder(tysos_driver); if (tysos_subdriver != null) { sb.Append("_"); sb.Append(tysos_subdriver); } string base_dev = sb.ToString(); if (next_device_id.ContainsKey(base_dev)) { dev_no = next_device_id[base_dev]; } sb.Append("_"); sb.Append(dev_no.ToString()); next_device_id[base_dev] = dev_no + 1; string dev_name = sb.ToString(); /* Link all PS/2 devices together */ if (tysos_driver == "ps2" && children.ContainsKey("ps2_0")) { props.AddRange(children["ps2_0"]); } /* Create a file system node for the device */ children[dev_name] = props; System.Diagnostics.Debugger.Log(0, "acpipc", "AddDevice: created device: " + dev_name); foreach (tysos.lib.File.Property prop in props) { System.Diagnostics.Debugger.Log(0, "acpipc", " " + prop.Name + ": " + prop.Value.ToString()); } }
private void AddDevice(string hid_str, string name, Aml.ACPIObject obj, Aml.Namespace n, Aml.IMachineInterface mi) { AddDevice(new string[] { hid_str }, name, obj, n, mi); }
internal ACPIObject Evaluate(IMachineInterface mi, Namespace.State s, Namespace n) { if (this == null) { throw new Exception("passed null pointer as this"); } /* Evaluate as much as we can */ switch (Type) { case DataType.Arg: return(s.Args[(int)Data]); case DataType.Buffer: return(this); case DataType.BufferField: { BufferFieldData bfd = Data as BufferFieldData; ACPIObject new_buf = bfd.Buffer.EvaluateTo(DataType.Buffer, mi, s, n); if (bfd.BitOffset % 8 != 0) { throw new NotImplementedException("BitOffset not divisible by 8"); } if (bfd.BitLength % 8 != 0) { throw new NotImplementedException("BitLength not divisible by 8"); } int byte_offset = bfd.BitOffset / 8; int byte_length = bfd.BitLength / 8; byte[] ret = new byte[byte_length]; byte[] src = (byte[])new_buf.Data; for (int i = 0; i < byte_length; i++) { ret[i] = src[byte_offset + i]; } return(new ACPIObject(DataType.Buffer, ret)); } case DataType.DDBHandle: throw new NotImplementedException("DDBHandle"); case DataType.Device: return(this); case DataType.Event: return(this); case DataType.FieldUnit: if (Data is FieldUnitData) { FieldUnitData fud = Data as FieldUnitData; ACPIObject op_region = fud.OpRegion; if (op_region.Type != DataType.OpRegion) { throw new Exception("Read from FieldUnit with invalid OpRegion type (" + op_region.Type.ToString() + ")"); } OpRegionData ord = op_region.Data as OpRegionData; /* Ensure the requested field index is within the opregion */ int byte_offset = fud.BitOffset / 8; int byte_length = fud.BitLength / 8; if ((ulong)byte_offset + (ulong)byte_length > ord.Length) { throw new Exception("Read: attempt to read to field beyond length of opregion (offset: " + byte_offset.ToString() + ", length: " + byte_length.ToString() + ", OpRegion.Length: " + ord.Length + ")"); } if (fud.BitOffset % 8 != 0) { throw new NotImplementedException("Read: non-byte aligned offset (" + fud.BitOffset.ToString() + ")"); } if (fud.BitLength % 8 != 0) { throw new NotImplementedException("Read: non-byte aligned length (" + fud.BitLength.ToString() + ")"); } /* Do the read depending on the op region type */ switch (ord.RegionSpace) { case 0: // Memory switch (byte_length) { case 1: return(mi.ReadMemoryByte(ord.Offset + (ulong)byte_offset)); case 2: return(mi.ReadMemoryWord(ord.Offset + (ulong)byte_offset)); case 4: return(mi.ReadMemoryDWord(ord.Offset + (ulong)byte_offset)); case 8: return(mi.ReadMemoryQWord(ord.Offset + (ulong)byte_offset)); default: throw new NotImplementedException("Read: unsupported byte length: " + byte_length.ToString()); } case 1: // IO switch (byte_length) { case 1: return(mi.ReadIOByte(ord.Offset + (ulong)byte_offset)); case 2: return(mi.ReadIOWord(ord.Offset + (ulong)byte_offset)); case 4: return(mi.ReadIODWord(ord.Offset + (ulong)byte_offset)); case 8: return(mi.ReadIOQWord(ord.Offset + (ulong)byte_offset)); default: throw new NotImplementedException("Read: unsupported byte length: " + byte_length.ToString()); } case 2: // PCI Configuration space { // try and get the _ADR object for the current device ACPIObject adr = n.Evaluate(ord.Device.ToString() + "._ADR", mi).EvaluateTo(DataType.Integer, mi, s, n); if (adr == null) { throw new Exception(ord.Device.ToString() + "._ADR failed"); } uint bus = 0; uint device = ((uint)adr.IntegerData >> 16) & 0xffffU; uint func = (uint)adr.IntegerData & 0xffffU; uint offset = (uint)ord.Offset + (uint)byte_offset; System.Diagnostics.Debugger.Log(0, "acpipc", "Read from PCI conf space for: " + ord.Device.ToString() + ", _ADR: (" + adr.Type.ToString() + ") " + adr.IntegerData.ToString("X")); switch (byte_length) { case 1: return(mi.ReadPCIByte(bus, device, func, offset)); case 2: return(mi.ReadPCIWord(bus, device, func, offset)); case 4: return(mi.ReadPCIDWord(bus, device, func, offset)); default: throw new NotImplementedException("Read: unsupported byte length: " + byte_length.ToString()); } } default: throw new NotImplementedException("Read: unsupported OpRegion type: " + ord.ToString()); } } else if (Data is IndexFieldUnitData) { var ifud = Data as IndexFieldUnitData; /* Ensure the requested field index is byte aligned */ int byte_offset = ifud.BitOffset / 8; int byte_length = ifud.BitLength / 8; if (ifud.BitOffset % 8 != 0) { throw new NotImplementedException("Read: non-byte aligned offset (" + ifud.BitOffset.ToString() + ")"); } if (ifud.BitLength % 8 != 0) { throw new NotImplementedException("Read: non-byte aligned length (" + ifud.BitLength.ToString() + ")"); } /* Write to index port, read from data port */ ifud.Index.Write((ulong)byte_offset, mi, s, n); var ret = ifud.Data.Evaluate(mi, s, n); switch (byte_length) { case 1: ret.Data = ret.IntegerData & 0xffU; break; case 2: ret.Data = ret.IntegerData & 0xffffU; break; } return(ret); } throw new NotSupportedException("Invalid FieldUnit data type: " + Data.ToString()); case DataType.Integer: return(this); case DataType.Local: return(s.Locals[(int)Data]); case DataType.Method: { Namespace.State new_state = new Namespace.State(); if (s.IsMethodExec) { new_state.Args = s.Args; } else { new_state.Args = new Dictionary <int, ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()); } new_state.Locals = new Dictionary <int, ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()); ACPIObject ret; new_state.Scope = Name; MethodData md = Data as MethodData; int midx = md.Offset; //System.Diagnostics.Debugger.Log(0, "acpipc", "Begin evaluating method: " + Name.ToString()); if (md == null) { throw new Exception("Method object has no MethodData"); } if (md.Builtin != null) { return(md.Builtin.Execute(new_state)); } if (!n.ParseTermList(md.AML, ref midx, md.Length, out ret, new_state)) { throw new Exception(); } return(ret); } case DataType.Mutex: return(this); case DataType.ObjectReference: //System.Diagnostics.Debugger.Log(0, "acpipc", "Begin evaluating object reference: " + ((ACPIObject.ObjRefData)Data).ToString()); return(this); case DataType.OpRegion: return(this); case DataType.Package: return(this); case DataType.PowerResource: return(this); case DataType.Processor: return(this); case DataType.String: return(this); case DataType.ThermalZone: return(this); case DataType.Uninitialized: return(this); default: throw new NotImplementedException(); } }
internal void Write(ACPIObject d, int Offset, IMachineInterface mi, Namespace.State s, Namespace n) { if (Type == DataType.Uninitialized || (Type == DataType.ObjectReference && ((ObjRefData)Data).Object == null) || (Type == DataType.Integer && (ulong)Data == 0UL)) { return; } //System.Diagnostics.Debugger.Log(0, "acpipc", "Write: " + d.Type.ToString() + " to " + Type.ToString()); switch (Type) { case DataType.Local: s.Locals[(int)Data] = d; return; case DataType.Arg: s.Args[(int)Data] = d; return; case DataType.Buffer: { ACPIObject new_buf = d.EvaluateTo(DataType.Buffer, mi, s, n); byte[] dst = (byte[])Data; byte[] src = (byte[])new_buf.Data; for (int i = Offset; i < Offset + dst.Length; i++) { if (i < src.Length) { dst[i] = src[i]; } else { dst[i] = 0; } } return; } case DataType.ObjectReference: { ObjRefData ord = Data as ObjRefData; ACPIObject dst = ord.Object; switch (dst.Type) { case DataType.Buffer: dst.Write(d, ord.Index, mi, s, n); return; case DataType.BufferField: dst.Write(d, mi, s, n); return; case DataType.FieldUnit: dst.Write(d, mi, s, n); return; case DataType.Integer: dst.Data = d.EvaluateTo(DataType.Integer, mi, s, n).IntegerData; return; default: throw new NotSupportedException("Write: " + d.Type + " to ObjectReference(" + dst.Type + ")"); } } case DataType.BufferField: { BufferFieldData bfd = Data as BufferFieldData; ACPIObject new_buf_src = d.EvaluateTo(DataType.Buffer, mi, s, n); ACPIObject new_buf_dst = bfd.Buffer.EvaluateTo(DataType.Buffer, mi, s, n); if (bfd.BitOffset % 8 != 0) { throw new NotImplementedException("BitOffset not divisible by 8"); } if (bfd.BitLength % 8 != 0) { throw new NotImplementedException("BitLength not divisible by 8"); } int byte_offset = bfd.BitOffset / 8; int byte_length = bfd.BitLength / 8; byte[] src = (byte[])new_buf_src.Data; byte[] dst = (byte[])new_buf_dst.Data; for (int i = 0; i < byte_length; i++) { dst[byte_offset + i] = src[i]; } return; } case DataType.FieldUnit: if (Data is FieldUnitData) { FieldUnitData fud = Data as FieldUnitData; ACPIObject op_region = fud.OpRegion; if (op_region.Type != DataType.OpRegion) { throw new Exception("Write to FieldUnit with invalid OpRegion type (" + op_region.Type.ToString() + ")"); } OpRegionData ord = op_region.Data as OpRegionData; /* Ensure the requested field index is within the opregion */ int byte_offset = fud.BitOffset / 8; int byte_length = fud.BitLength / 8; if ((ulong)byte_offset + (ulong)byte_length > ord.Length) { throw new Exception("Write: attempt to write to field beyond length of opregion (offset: " + byte_offset.ToString() + ", length: " + byte_length.ToString() + ", OpRegion.Length: " + ord.Length + ")"); } if (fud.BitOffset % 8 != 0) { throw new NotImplementedException("Write: non-byte aligned offset (" + fud.BitOffset.ToString() + ")"); } if (fud.BitLength % 8 != 0) { throw new NotImplementedException("Write: non-byte aligned length (" + fud.BitLength.ToString() + ")"); } /* Get the data */ ulong int_val = d.EvaluateTo(DataType.Integer, mi, s, n).IntegerData; /* Do the write depending on the op region type */ switch (ord.RegionSpace) { case 0: // Memory switch (byte_length) { case 1: mi.WriteMemoryByte(ord.Offset + (ulong)byte_offset, (byte)(int_val & 0xff)); return; case 2: mi.WriteMemoryWord(ord.Offset + (ulong)byte_offset, (ushort)(int_val & 0xffff)); return; case 4: mi.WriteMemoryDWord(ord.Offset + (ulong)byte_offset, (uint)(int_val & 0xffffff)); return; case 8: mi.WriteMemoryQWord(ord.Offset + (ulong)byte_offset, int_val); return; default: throw new NotImplementedException("Write: unsupported byte length: " + byte_length.ToString()); } case 1: // IO switch (byte_length) { case 1: mi.WriteIOByte(ord.Offset + (ulong)byte_offset, (byte)(int_val & 0xff)); return; case 2: mi.WriteIOWord(ord.Offset + (ulong)byte_offset, (ushort)(int_val & 0xffff)); return; case 4: mi.WriteIODWord(ord.Offset + (ulong)byte_offset, (uint)(int_val & 0xffffff)); return; case 8: mi.WriteIOQWord(ord.Offset + (ulong)byte_offset, int_val); return; default: throw new NotImplementedException("Write: unsupported byte length: " + byte_length.ToString()); } case 2: // PCI Configuration space { // try and get the _ADR object for the current device ACPIObject adr = n.Evaluate(ord.Device.ToString() + "._ADR", mi).EvaluateTo(DataType.Integer, mi, s, n); if (adr == null) { throw new Exception(ord.Device.ToString() + "._ADR failed"); } uint bus = 0; uint device = ((uint)adr.IntegerData >> 16) & 0xffffU; uint func = (uint)adr.IntegerData & 0xffffU; uint offset = (uint)ord.Offset + (uint)byte_offset; switch (byte_length) { case 1: mi.WritePCIByte(bus, device, func, offset, (byte)int_val); return; case 2: mi.WritePCIWord(bus, device, func, offset, (ushort)int_val); return; case 4: mi.WritePCIDWord(bus, device, func, offset, (uint)int_val); return; default: throw new NotImplementedException("Write: unsupported byte length: " + byte_length.ToString()); } } default: throw new NotImplementedException("Write: unsupported OpRegion type: " + ord.ToString()); } } else if (Data is IndexFieldUnitData) { var ifud = Data as IndexFieldUnitData; /* Ensure the requested field index is byte aligned */ int byte_offset = ifud.BitOffset / 8; int byte_length = ifud.BitLength / 8; if (ifud.BitOffset % 8 != 0) { throw new NotImplementedException("Read: non-byte aligned offset (" + ifud.BitOffset.ToString() + ")"); } if (ifud.BitLength % 8 != 0) { throw new NotImplementedException("Read: non-byte aligned length (" + ifud.BitLength.ToString() + ")"); } /* Get the data */ ulong int_val = d.EvaluateTo(DataType.Integer, mi, s, n).IntegerData; /* Write to index port, write to data port */ ifud.Index.Write((ulong)byte_offset, mi, s, n); ifud.Data.Write(int_val, mi, s, n); return; } else { throw new NotSupportedException("Invalid FieldUnit data type: " + Data.ToString()); } default: throw new NotImplementedException("Write: " + Type.ToString()); } throw new NotImplementedException(); }
internal void Write(ACPIObject d, IMachineInterface mi, Namespace.State s, Namespace n) { Write(d, 0, mi, s, n); }
internal static ACPIObject ConvertTo(ACPIObject source, DataType dest_type) { if (source.Type == dest_type) { return(source); } /* Then try to convert the data if required */ switch (source.Type) { case DataType.String: { string src = (string)source.Data; switch (dest_type) { case DataType.Buffer: { byte[] dst = new byte[src.Length]; for (int i = 0; i < src.Length; i++) { dst[i] = (byte)src[i]; } return(new ACPIObject(DataType.Buffer, dst)); } case DataType.Integer: { ulong ret = 0; int digits = 0; foreach (char c in src) { if (digits == 16) { break; } ulong cur_digit = 0; if (c >= '0' && c <= '9') { cur_digit = (ulong)(c - '0'); } else if (c >= 'a' && c <= 'f') { cur_digit = (ulong)(c - 'a') + 0xa; } else if (c >= 'A' && c <= 'F') { cur_digit = (ulong)(c - 'A') + 0xa; } else { break; } ret <<= 4; ret |= cur_digit; digits++; } return(new ACPIObject(DataType.Integer, digits)); } } } break; case DataType.Integer: { ulong src = source.IntegerData; switch (dest_type) { case DataType.Buffer: { byte[] dst = new byte[8]; for (int i = 0; i < 8; i++) { dst[i] = (byte)(src & 0xff); src >>= 8; } return(new ACPIObject(DataType.Buffer, dst)); } } } break; case DataType.Buffer: { byte[] src = (byte[])source.Data; switch (dest_type) { case DataType.Integer: { ulong dst = 0; for (int i = 0; i < src.Length; i++) { byte v = src[i]; if (i > 8) { if (v != 0) { throw new Exception("Unable to convert large buffer to integer"); } } else { dst |= (((ulong)v) << (i * 8)); } } return(new ACPIObject(DataType.Integer, dst)); } } } break; } throw new NotImplementedException("Convert " + source.Type.ToString() + " to " + dest_type.ToString()); }
public override bool InitServer() { /* Interpret the resources we have */ foreach (tysos.lib.File.Property p in props) { if (p.Name.StartsWith("table_")) { System.Diagnostics.Debugger.Log(0, null, "adding table\n"); tables.Add(Table.InterpretTable(p.Value as tysos.VirtualMemoryResource64, this)); } if (p.Name == "interrupts") { cpu_interrupts.AddRange(p.Value as IEnumerable <tysos.Resources.InterruptLine>); } } vmems.Init(props); pmems.Init(props); ios.Init(props); System.Diagnostics.Debugger.Log(0, null, "finished parsing resources\n"); /* Execute drivers for any IOAPICs we've found */ List <tysos.ServerObject> ioapics = new List <tysos.ServerObject>(); foreach (var table in tables) { if (table is APIC) { APIC apic = table as APIC; foreach (APICStructure apicstruct in apic.APICs) { if (apicstruct is IOAPICStructure) { IOAPICStructure ias = apicstruct as IOAPICStructure; List <File.Property> ias_props = new List <File.Property>(); ias_props.Add(new File.Property { Name = "pmem", Value = pmems.AllocFixed(ias.IOAPICAddress, 0x1000) }); ias_props.Add(new File.Property { Name = "vmem", Value = vmems.Alloc(0x1000) }); ias_props.Add(new File.Property { Name = "gsibase", Value = ias.GSIBase }); ias_props.Add(new File.Property { Name = "ioapicid", Value = ias.IOAPICID }); ias_props.Add(new File.Property { Name = "interrupts", Value = cpu_interrupts }); string a_name = "ioapic_" + ias.IOAPICID.ToString(); children.Add(a_name, ias_props); System.Diagnostics.Debugger.Log(0, "acpipc", "Starting IOAPIC driver for " + a_name); ioapic.ioapic ioapic = new ioapic.ioapic(ias_props.ToArray()); tysos.Process p_ioapic = tysos.Process.CreateProcess(a_name, new System.Threading.ThreadStart(ioapic.MessageLoop), new object[] { ioapic }); p_ioapic.Start(); gsi_providers.Add(ioapic); } else if (apicstruct is InterruptSourceOverrideStructure) { isos.Add(apicstruct as InterruptSourceOverrideStructure); } else if (apicstruct is LocalAPICStructure) { lapics.Add(apicstruct as LocalAPICStructure); } } } } /* Generate interrupt resources for the standard ISA IRQs */ for (int i = 0; i < 16; i++) { isa_irqs[i] = GenerateISAIRQ(i); } /* Dump VBox ACPI interface */ /*var vbox_idx = ios.AllocFixed(0x4048, 4); * var vbox_dat = ios.AllocFixed(0x404c, 4); * for(uint i = 0; i < 26; i++) * { * vbox_idx.Write(vbox_idx.Addr64, 4, i * 4); * var val = vbox_dat.Read(vbox_dat.Addr64, 4); * System.Diagnostics.Debugger.Log(0, "acpipc", "VBoxACPI: " + i.ToString() + ": " + val.ToString("X8")); * }*/ /* Now allocate space for the DSDT */ if (p_dsdt_addr == 0) { throw new Exception("DSDT not found"); } ulong dsdt_offset = p_dsdt_addr & 0xfffUL; tysos.PhysicalMemoryResource64 p_dsdt = pmems.AllocFixed(p_dsdt_addr, dsdt_len); tysos.VirtualMemoryResource64 v_dsdt = vmems.Alloc(dsdt_len + dsdt_offset, 0x1000); System.Diagnostics.Debugger.Log(0, null, "Mapping first page of DSDT from " + p_dsdt.Addr64.ToString("X16") + " (requested " + p_dsdt_addr.ToString("X16") + ") to vmem " + v_dsdt.Addr64.ToString("X16") + ", length: " + v_dsdt.Length64.ToString("X")); p_dsdt.Map(v_dsdt); if ((p_dsdt_addr & 0xfffUL) != 0UL) { v_dsdt = v_dsdt.Split(v_dsdt.Addr64 + (p_dsdt_addr & 0xfffUL), dsdt_len) as tysos.VirtualMemoryResource64; } dsdt_len = v_dsdt.Read(v_dsdt.Addr64 + 4, 4); System.Diagnostics.Debugger.Log(0, "acpipc", "DSDT table length " + dsdt_len.ToString("X16")); p_dsdt = pmems.AllocFixed(p_dsdt_addr, dsdt_len, true); v_dsdt = vmems.Alloc(dsdt_len + dsdt_offset, 0x1000); p_dsdt.Map(v_dsdt); if ((p_dsdt_addr & 0xfffUL) != 0UL) { v_dsdt = v_dsdt.Split(v_dsdt.Addr64 + (p_dsdt_addr & 0xfffUL), dsdt_len) as tysos.VirtualMemoryResource64; } System.Diagnostics.Debugger.Log(0, "acpipc", "DSDT region: " + v_dsdt.Addr64.ToString("X16") + " - " + (v_dsdt.Addr64 + v_dsdt.Length64).ToString("X16")); /* Execute the DSDT followed by SSDTs */ mi = new MachineInterface(this); n = new Aml.Namespace(mi); System.Diagnostics.Debugger.Log(0, "acpipc", "Executing DSDT"); Aml.DefBlockHeader h = new Aml.DefBlockHeader(); int idx = 0; byte[] aml = v_dsdt.ToArray(); n.ParseDefBlockHeader(aml, ref idx, h); System.Diagnostics.Debugger.Log(0, "acpipc", "DSDT OEM: " + h.OemID + ", TableID: " + h.OemTableID); if (h.OemID.Equals("VBOX ")) { System.Diagnostics.Debugger.Log(0, "acpipc", "VirtualBox BIOS detected"); mi.is_vbox = true; } System.Diagnostics.Debugger.Log(0, "acpipc", "DefBlockHeader parsed"); Aml.Namespace.State s = new Aml.Namespace.State { Args = new Dictionary <int, Aml.ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()), Locals = new Dictionary <int, Aml.ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()), Scope = Aml.ACPIName.RootName }; n.ParseTermList(aml, ref idx, -1, s); System.Diagnostics.Debugger.Log(0, "acpipc", "DSDT parsed"); foreach (tysos.VirtualMemoryResource64 v_ssdt in ssdts) { System.Diagnostics.Debugger.Log(0, "acpipc", "Executing SSDT"); idx = 0; byte[] ssdt_aml = v_ssdt.ToArray(); Aml.DefBlockHeader h_ssdt = new Aml.DefBlockHeader(); n.ParseDefBlockHeader(ssdt_aml, ref idx, h_ssdt); System.Diagnostics.Debugger.Log(0, "acpipc", "DefBlockHeader parsed"); s = new Aml.Namespace.State { Args = new Dictionary <int, Aml.ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()), Locals = new Dictionary <int, Aml.ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()), Scope = Aml.ACPIName.RootName }; n.ParseTermList(ssdt_aml, ref idx, -1, s); System.Diagnostics.Debugger.Log(0, "acpipc", "SSDT parsed"); } /* Initialize the namespace * * To do this we: * 1) initialize the main namespace (\_SB_._INI) * 2) run each device's _STA method. * - if _STA & 0x1 = 0, * - if _STA & 0x8 = 0 remove device and children from namespace * - else remove device (but still enumerate children) * - else, run _INI on device * 3) tell ACPI we are using IOAPIC (\_PIC(1)) */ EvaluateObject("\\_SB_._INI"); /* We do the initialization this way to ensure we always initialize * root objects before children. By definition parent objects have * shorter names than children, therefore we do all devices of length 1, * then 2 etc until all have been covered. * * If we find a non-functional device (bit 3 not set), we at that stage * find all children of it and mark them as already initialized (so that * they are not parsed in the loop) */ int num_to_parse = n.Devices.Count; List <string> dev_names = new List <string>(n.Devices.Keys); int depth = 1; while (num_to_parse > 0) { for (int i = 0; i < dev_names.Count; i++) { ACPIName dev_name = dev_names[i]; if (dev_name == null) { continue; } if (dev_name.ElementCount != depth) { continue; } ACPIObject dev_obj = n.FindObject(dev_name); if (dev_obj.Initialized) { continue; } System.Diagnostics.Debugger.Log(0, "acpipc", "Executing " + dev_name + "._STA"); // Run _STA on the device int sta_val = 0; var sta = n.EvaluateTo(dev_name + "._STA", mi, ACPIObject.DataType.Integer); if (sta == null) { sta_val = 0xf; } else { sta_val = (int)sta.IntegerData; } dev_obj.Present = ((sta_val & 0x1) != 0); dev_obj.Functioning = ((sta_val & 0x8) != 0); if (dev_obj.Present == false && dev_obj.Functioning == false) { // Do not run _INI, do not examine device children System.Diagnostics.Debugger.Log(0, "acpipc", "Device is not present or functioning. Disabling children"); for (int j = 0; j < dev_names.Count; j++) { ACPIName subdev_name = dev_names[j]; if (subdev_name == null) { continue; } if (subdev_name.ElementCount <= dev_name.ElementCount) { continue; } bool is_subdev = true; for (int k = 0; k < dev_name.ElementCount; k++) { if (subdev_name.NameElement(k).Equals(dev_name.NameElement(k)) == false) { is_subdev = false; break; } } if (is_subdev) { System.Diagnostics.Debugger.Log(0, "acpipc", "Disabling child " + subdev_name); num_to_parse--; dev_names[j] = null; } } } else if (dev_obj.Present) { // Run _INI, examine children System.Diagnostics.Debugger.Log(0, "acpipc", "Executing " + dev_name + "._INI"); n.Evaluate(dev_name + "._INI", mi); dev_obj.Initialized = true; } num_to_parse--; } depth++; } System.Diagnostics.Debugger.Log(0, "acpipc", "Executing \\_PIC"); EvaluateObject("\\_PIC", new ACPIObject[] { 1 }); /* Generate a list of PCI Interrupt Links - we pass these as resources * to PCI devices */ foreach (KeyValuePair <string, Aml.ACPIObject> kvp in n.Devices) { if (kvp.Value.Initialized == false) { continue; } var hid = n.EvaluateTo(kvp.Key + "._HID", mi, ACPIObject.DataType.Integer); if (hid == null) { continue; } if (hid.IntegerData == 0x0f0cd041U) { lnks.Add(kvp.Key); } } /* Now extract a list of devices that have a _HID object. * These are the only ones ACPI needs to enumerate, all others are * enumerated by the respective bus enumerator */ foreach (KeyValuePair <string, Aml.ACPIObject> kvp in n.Devices) { List <string> hid_strs = new List <string>(); Aml.ACPIObject hid = n.FindObject(kvp.Key + "._HID", false); if (hid == null) { continue; } if (kvp.Value.Initialized == false) { continue; } s = new Aml.Namespace.State { Args = new Dictionary <int, Aml.ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()), Locals = new Dictionary <int, Aml.ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()), Scope = hid.Name }; Aml.ACPIObject hid_ret = hid.Evaluate(mi, s, n); string hid_str = ""; switch (hid_ret.Type) { case Aml.ACPIObject.DataType.Integer: hid_str = hid_ret.IntegerData.ToString("X8"); break; case Aml.ACPIObject.DataType.String: hid_str = (string)hid_ret.Data; break; default: hid_str = hid_ret.Type.ToString() + ": " + hid_ret.Data.ToString(); break; } hid_strs.Add(hid_str); /* Also add all compatible IDs */ Aml.ACPIObject cid = n.Evaluate(kvp.Key + "._CID", mi); if (cid != null) { switch (cid.Type) { case ACPIObject.DataType.Integer: hid_strs.Add(cid.IntegerData.ToString("X8")); break; case ACPIObject.DataType.String: hid_strs.Add(cid.Data as string); break; case ACPIObject.DataType.Package: var pd = cid.Data as Aml.ACPIObject[]; foreach (var icid in pd) { switch (icid.Type) { case ACPIObject.DataType.Integer: hid_strs.Add(icid.IntegerData.ToString("X8")); break; case ACPIObject.DataType.String: hid_strs.Add(icid.Data as string); break; default: hid_strs.Add(icid.Type.ToString() + ": " + icid.Data.ToString()); break; } } break; default: hid_strs.Add(cid.Type.ToString() + ": " + cid.Data.ToString()); break; } } AddDevice(hid_strs, kvp.Key, kvp.Value, n, mi); } foreach (KeyValuePair <string, Aml.ACPIObject> kvp in n.Processors) { AddDevice("cpu", kvp.Key, kvp.Value, n, mi); } /* Take command of hardware resources */ if (fadt != null) { /* Say that we handle fixed power and sleep button events */ fadt.PM1_EN.Write((1UL << 8) | (1UL << 9)); System.Diagnostics.Debugger.Log(0, null, "FADT: " + "PM1a_EVT_BLK: " + fadt.PM1a_EVT_BLK.ToString() + ", PM1a_CNT_BLK: " + fadt.PM1a_CNT_BLK.ToString() + ", PM1b_EVT_BLK: " + fadt.PM1b_EVT_BLK.ToString() + ", PM1b_CNT_BLK: " + fadt.PM1b_CNT_BLK.ToString() + ", PM2_CNT_BLK: " + fadt.PM2_CNT_BLK.ToString() + ", PM_TMR_BLK: " + fadt.PM_TMR_BLK.ToString() + ", GPE0_BLK: " + fadt.GPE0_BLK.ToString() + ", GPE1_BLK: " + fadt.GPE1_BLK.ToString()); var sci = isa_irqs[fadt.SCI_INT]; if (sci != null) { System.Diagnostics.Debugger.Log(0, null, "SCI_INT mapped to " + sci.ToString()); sci.RegisterHandler(new tysos.Resources.InterruptLine.InterruptHandler(SCIInt)); } /* Set ACPI mode */ var smi_cmd = ios.AllocFixed(fadt.SMI_CMD, 1, true); if (smi_cmd != null) { if ((fadt.PM1_CNT.Read() & 0x1) != 0) { System.Diagnostics.Debugger.Log(0, null, "Already in ACPI mode"); } else { System.Diagnostics.Debugger.Log(0, null, "Setting ACPI mode"); smi_cmd.Write(smi_cmd.Addr64, 1, fadt.ACPI_ENABLE); while ((fadt.PM1_CNT.Read() & 0x1) == 0) { ; } System.Diagnostics.Debugger.Log(0, null, "Set ACPI mode"); } } } root.Add(new File.Property { Name = "class", Value = "bus" }); Tags.Add("class"); return(true); }