Example #1
0
        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);
        }
Example #2
0
        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);
        }