internal static Table InterpretTable(tysos.VirtualMemoryResource64 table, acpipc a) { Table ret; char[] sig = new char[4]; sig[0] = (char)table.Read(table.Addr64, 1); sig[1] = (char)table.Read(table.Addr64 + 1, 1); sig[2] = (char)table.Read(table.Addr64 + 2, 1); sig[3] = (char)table.Read(table.Addr64 + 3, 1); string sig_string = new string(sig); // Check checksum uint length = (uint)table.Read(table.Addr64 + 4, 4); byte csum = 0; unchecked { for (uint i = 0; i < length; i++) { csum += (byte)table.Read(table.Addr64 + i, 1); } } System.Diagnostics.Debugger.Log(0, "acpipc", "Found table with signature " + sig_string + " at " + table.Addr64.ToString("X16") + " (length " + length.ToString("X8") + ")"); if (csum == 0) { System.Diagnostics.Debugger.Log(0, "acpipc", "table checksum passed"); } else { System.Diagnostics.Debugger.Log(0, "acpipc", "table checksum failed: " + csum.ToString()); } if (sig_string == "FACP") { FADT f = new FADT(); f.FIRMWARE_CTRL = (length >= 140) ? table.Read(table.Addr64 + 132, 8) : 0; if (f.FIRMWARE_CTRL == 0) { f.FIRMWARE_CTRL = table.Read(table.Addr64 + 36, 4); } f.DSDT = (length >= 148) ? table.Read(table.Addr64 + 140, 8) : 0; if (f.DSDT == 0) { f.DSDT = table.Read(table.Addr64 + 40, 4); } f.Preferred_PM_Profile = (byte)table.Read(table.Addr64 + 45, 1); f.SCI_INT = (ushort)table.Read(table.Addr64 + 46, 2); f.SMI_CMD = (uint)table.Read(table.Addr64 + 48, 4); f.ACPI_ENABLE = (byte)table.Read(table.Addr64 + 52, 1); f.ACPI_DISABLE = (byte)table.Read(table.Addr64 + 53, 1); f.S4BIOS_REQ = (byte)table.Read(table.Addr64 + 54, 1); f.PSTATE_CNT = (byte)table.Read(table.Addr64 + 55, 1); f.PM1_EVT_LEN = (uint)table.Read(table.Addr64 + 88, 1); f.PM1_CNT_LEN = (uint)table.Read(table.Addr64 + 89, 1); f.PM2_CNT_LEN = (uint)table.Read(table.Addr64 + 90, 1); f.PM_TMR_LEN = (uint)table.Read(table.Addr64 + 91, 1); f.GPE0_BLK_LEN = (uint)table.Read(table.Addr64 + 92, 1); f.GPE1_BLK_LEN = (uint)table.Read(table.Addr64 + 93, 1); f.GPE1_BASE = (uint)table.Read(table.Addr64 + 94, 1); f.PM1a_EVT_BLK = new GAS((uint)table.Read(table.Addr64 + 56, 4), f.PM1_EVT_LEN * 8, a); f.PM1b_EVT_BLK = new GAS((uint)table.Read(table.Addr64 + 60, 4), f.PM1_EVT_LEN * 8, a); f.PM1a_CNT_BLK = new GAS((uint)table.Read(table.Addr64 + 64, 4), f.PM1_CNT_LEN * 8, a); f.PM1b_CNT_BLK = new GAS((uint)table.Read(table.Addr64 + 68, 4), f.PM1_CNT_LEN * 8, a); f.PM2_CNT_BLK = new GAS((uint)table.Read(table.Addr64 + 72, 4), f.PM2_CNT_LEN * 8, a); f.PM_TMR_BLK = new GAS((uint)table.Read(table.Addr64 + 76, 4), f.PM_TMR_LEN * 8, a); f.GPE0_BLK = new GAS((uint)table.Read(table.Addr64 + 76, 4), f.GPE0_BLK_LEN * 8, a); f.GPE1_BLK = new GAS((uint)table.Read(table.Addr64 + 76, 4), f.GPE1_BLK_LEN * 8, a); if (length >= 244) { if (table.Read(table.Addr64 + 152, 8) != 0) { f.PM1a_EVT_BLK = new GAS(table, 148, a); } if (table.Read(table.Addr64 + 164, 8) != 0) { f.PM1b_EVT_BLK = new GAS(table, 160, a); } if (table.Read(table.Addr64 + 176, 8) != 0) { f.PM1a_CNT_BLK = new GAS(table, 172, a); } if (table.Read(table.Addr64 + 188, 8) != 0) { f.PM1b_CNT_BLK = new GAS(table, 184, a); } if (table.Read(table.Addr64 + 200, 8) != 0) { f.PM2_CNT_BLK = new GAS(table, 196, a); } if (table.Read(table.Addr64 + 212, 8) != 0) { f.PM_TMR_BLK = new GAS(table, 208, a); } if (table.Read(table.Addr64 + 224, 8) != 0) { f.GPE0_BLK = new GAS(table, 220, a); } if (table.Read(table.Addr64 + 236, 8) != 0) { f.GPE1_BLK = new GAS(table, 232, a); } } f.PM1_EVT = new RegGroup(f.PM1a_EVT_BLK, f.PM1b_EVT_BLK); f.PM1_CNT = new RegGroup(f.PM1a_CNT_BLK, f.PM1b_CNT_BLK); f.PM1_STS = new SplitReg(f.PM1_EVT, 0, f.PM1a_EVT_BLK.BitWidth / 2); f.PM1_EN = new SplitReg(f.PM1_EVT, f.PM1a_EVT_BLK.BitWidth / 2, f.PM1a_EVT_BLK.BitWidth / 2); f.GPE0_STS = new SplitReg(f.GPE0_BLK, 0, (int)f.GPE0_BLK_LEN * 4); f.GPE0_EN = new SplitReg(f.GPE0_BLK, (int)f.GPE0_BLK_LEN * 4, (int)f.GPE0_BLK_LEN * 4); f.GPE1_STS = new SplitReg(f.GPE1_BLK, 0, (int)f.GPE1_BLK_LEN * 4); f.GPE1_EN = new SplitReg(f.GPE1_BLK, (int)f.GPE1_BLK_LEN * 4, (int)f.GPE1_BLK_LEN * 4); f.IAPC_BOOT_ARCH = (ushort)table.Read(table.Addr64 + 109, 2); f.Flags = (uint)table.Read(table.Addr64 + 112, 4); System.Diagnostics.Debugger.Log(0, "acpipc", "FADT table: DSDT: " + f.DSDT.ToString("X16") + ", FIRMWARE_CTRL: " + f.FIRMWARE_CTRL.ToString("X16") + ", Preferred_PM_Profile: " + f.Preferred_PM_Profile.ToString() + ", IAPC_BOOT_ARCH: " + f.IAPC_BOOT_ARCH.ToString("X4") + ", Flags: " + f.Flags.ToString("X8") + "\n"); /* Store the DSDT details */ a.p_dsdt_addr = f.DSDT; a.dsdt_len = 36; // changed later after the DSDT is loaded ret = f; a.fadt = f; } else if (sig_string == "APIC") { APIC atbl = new APIC(); atbl.LocalAPICAddress = (ulong)table.Read(table.Addr64 + 36, 4); atbl.Flags = (uint)table.Read(table.Addr64 + 40, 4); atbl.APICs = new List <APICStructure>(); System.Diagnostics.Debugger.Log(0, "acpipc", "ACPI table: LocalAPICAddress: " + atbl.LocalAPICAddress.ToString("X16") + ", Flags: " + atbl.Flags.ToString("X8") + "\n"); uint cur_addr = 44; while (cur_addr < length) { APICStructure s; uint type = (uint)table.Read(table.Addr64 + cur_addr, 1); uint s_length = (uint)table.Read(table.Addr64 + cur_addr + 1, 1); if (type == 0) { LocalAPICStructure las = new LocalAPICStructure(); las.ACPIProcessorID = (uint)table.Read(table.Addr64 + cur_addr + 2, 1); las.APICID = (uint)table.Read(table.Addr64 + cur_addr + 3, 1); las.Flags = (uint)table.Read(table.Addr64 + cur_addr + 4, 4); System.Diagnostics.Debugger.Log(0, "acpipc", "LocalAPICStructure: " + "ACPIProcessorID: " + las.ACPIProcessorID.ToString("X8") + ", APICID: " + las.APICID.ToString("X8") + ", Flags: " + las.Flags.ToString("X8") + "\n"); s = las; } else if (type == 1) { IOAPICStructure ias = new IOAPICStructure(); ias.IOAPICID = (uint)table.Read(table.Addr64 + cur_addr + 2, 1); ias.IOAPICAddress = (ulong)table.Read(table.Addr64 + cur_addr + 4, 4); ias.GSIBase = (uint)table.Read(table.Addr64 + cur_addr + 8, 4); System.Diagnostics.Debugger.Log(0, "acpipc", "IOAPICStructure: " + "IOAPICID: " + ias.IOAPICID.ToString("X8") + ", IOAPICAddress: " + ias.IOAPICAddress.ToString("X16") + ", GSIBase: " + ias.GSIBase.ToString("X8") + "\n"); s = ias; } else if (type == 2) { InterruptSourceOverrideStructure iso = new InterruptSourceOverrideStructure(); iso.Bus = (int)table.Read(table.Addr64 + cur_addr + 2, 1); iso.Source = (int)table.Read(table.Addr64 + cur_addr + 3, 1); iso.GSI = (uint)table.Read(table.Addr64 + cur_addr + 4, 4); iso.Flags = (uint)table.Read(table.Addr64 + cur_addr + 8, 2); System.Diagnostics.Debugger.Log(0, "acpipc", "InterruptSourceOverrideStructure: " + "Bus: " + iso.Bus.ToString("X8") + ", Source: " + iso.Source.ToString("X16") + ", GSI: " + iso.GSI.ToString("X8") + ", Flags: " + iso.Flags.ToString("X8") + "\n"); s = iso; } else { System.Diagnostics.Debugger.Log(0, "acpipc", "APICStructure: unsupported type: " + type.ToString() + "\n"); s = new APICStructure(); } s.Length = (int)s_length; s.Type = (int)type; atbl.APICs.Add(s); cur_addr += s_length; } ret = atbl; } else if (sig_string == "SSDT") { ret = new Table(); ulong ssdt_vaddr = table.Addr64; ulong ssdt_length = length; tysos.VirtualMemoryResource64 ssdt_region = table.Split(ssdt_vaddr, ssdt_length) as tysos.VirtualMemoryResource64; System.Diagnostics.Debugger.Log(0, "acpipc", "ACPI table: SSDT: " + ssdt_vaddr.ToString("X16") + " - " + (ssdt_vaddr + ssdt_length).ToString("X16")); a.ssdts.Add(ssdt_region); } else { System.Diagnostics.Debugger.Log(0, "acpipc", "ACPI table: " + sig_string); ret = new Table(); } ret.signature = sig_string; ret.vmem = table; return(ret); }
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); }