Example #1
0
        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));
        }
Example #2
0
        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);
        }
Example #3
0
        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));
        }
Example #4
0
        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);
        }
Example #5
0
        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);
        }
Example #6
0
        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();
            }
        }
Example #7
0
        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());
            }
        }
Example #8
0
 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);
 }
Example #9
0
        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();
            }
        }
Example #10
0
        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();
        }
Example #11
0
 internal void Write(ACPIObject d, IMachineInterface mi, Namespace.State s, Namespace n)
 {
     Write(d, 0, mi, s, n);
 }
Example #12
0
        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());
        }
Example #13
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);
        }