Advertisement
Guest User

ACPI

a guest
Dec 23rd, 2014
273
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.16 KB | None | 0 0
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using Cosmos.Core;
  4.  
  5. namespace CosmosOS {
  6.  
  7. public unsafe class ACPI {
  8.     private static int* SMI_CMD;
  9.     private static byte ACPI_ENABLE;
  10.     private static byte ACPI_DISABLE;
  11.     private static int* PM1a_CNT;
  12.     private static int* PM1b_CNT;
  13.     private static short SLP_TYPa;
  14.     private static short SLP_TYPb;
  15.     private static short SLP_EN;
  16.     private static short SCI_EN;
  17.     private static byte PM1_CNT_LEN;
  18.  
  19.  
  20.     static int Compare(string c1, byte* c2) {
  21.  
  22.         for (int i = 0; i < c1.Length; i++) {
  23.             if (c1[i] != (char)c2[i]) {
  24.                 return -1;
  25.             }
  26.         }
  27.         return 0;
  28.     }
  29.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  30.     struct RSDPtr {
  31.         public fixed byte Signature[8];
  32.         public byte CheckSum;
  33.         public fixed byte OemID[6];
  34.         public byte Revision;
  35.         public int RsdtAddress;
  36.     };
  37.  
  38.  
  39.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  40.     struct FACP {
  41.         public fixed byte Signature[4];
  42.         public int Length;
  43.  
  44.         public fixed byte unneded1[40 - 8];
  45.         public int* DSDT;
  46.         public fixed byte unneded2[48 - 44];
  47.         public int* SMI_CMD;
  48.         public byte ACPI_ENABLE;
  49.         public byte ACPI_DISABLE;
  50.         public fixed byte unneded3[64 - 54];
  51.         public int* PM1a_CNT_BLK;
  52.         public int* PM1b_CNT_BLK;
  53.         public fixed byte unneded4[89 - 72];
  54.         public byte PM1_CNT_LEN;
  55.     };
  56.     static byte* Facp = null;
  57.     static int* facpget(int number) {
  58.  
  59.         if (number == 0) {
  60.             return (int*)*((int*)(Facp + 40));
  61.         } else if (number == 1) {
  62.             return (int*)*((int*)(Facp + 48));
  63.         } else if (number == 2) {
  64.             return (int*)*((int*)(Facp + 64));
  65.         } else if (number == 3) {
  66.             return (int*)*((int*)(Facp + 68));
  67.         } else {
  68.             return null;
  69.         }
  70.  
  71.     }
  72.     static byte facpbget(int number) {
  73.         if (number == 0) {
  74.             return *(Facp + 52);
  75.         } else if (number == 1) {
  76.             return *(Facp + 53);
  77.         } else if (number == 2) {
  78.             return *(Facp + 89);
  79.         } else {
  80.             return 0;
  81.         }
  82.     }
  83.     // check if the given address has a valid header
  84.     static uint* acpiCheckRSDPtr(uint* ptr) {
  85.         string sig = "RSD PTR ";
  86.         RSDPtr* rsdp = (RSDPtr*)ptr;
  87.         byte* bptr;
  88.         byte check = 0;
  89.         int i;
  90.  
  91.         if (Compare(sig, (byte*)rsdp) == 0) {
  92.             // check checksum rsdpd
  93.             bptr = (byte*)ptr;
  94.             for (i = 0; i < 20; i++) {
  95.                 check += *bptr;
  96.                 bptr++;
  97.             }
  98.             //Console.WriteLine("0x" + check.ToHex());
  99.             // found valid rsdpd
  100.             if (check == 0) {
  101.                 //string str = rsdp->RsdtAddress.ToHex();
  102.                 //Console.WriteLine("seen"); Console.WriteLine(str);
  103.                 Compare("RSDT", (byte*)rsdp->RsdtAddress);
  104.                 if (rsdp->RsdtAddress != 0) {
  105.                     return (uint*)rsdp->RsdtAddress;
  106.                 }
  107.             }
  108.         }
  109.         Console.WriteLine("Unable to find RSDT. ACPI not available");
  110.         return null;
  111.     }
  112.  
  113.     static unsafe uint RSDPAddress() {
  114.  
  115.         // check bios
  116.         for (uint addr = 0xE0000; addr < 0x100000; addr += 4)
  117.             if (Compare("RSD PTR ", (byte*)addr) == 0)
  118.                 if (Check_RSD(addr)) {
  119.                     return addr;
  120.                 }
  121.         // check extended bios
  122.         uint ebda_address = *((uint*)0x040E);
  123.  
  124.         ebda_address = (ebda_address * 0x10) & 0x000fffff;
  125.  
  126.         for (uint addr = ebda_address; addr < ebda_address + 1024; addr += 4)
  127.             if (Compare("RSD PTR ", (byte*)addr) == 0) {
  128.                 return addr;
  129.             }
  130.  
  131.         // not found
  132.         return 0;
  133.     }
  134.     // checks for a given header and validates checksum
  135.     static int acpiCheckHeader(byte* ptr, string sig) {
  136.         return Compare(sig, ptr);
  137.     }
  138.  
  139.     static bool Check_RSD(uint address) {
  140.         byte sum = 0;
  141.         byte* check = (byte*)address;
  142.  
  143.         for (int i = 0; i < 20; i++) {
  144.             sum += *(check++);
  145.         }
  146.  
  147.         return (sum == 0);
  148.     }
  149.     private static Cosmos.Core.IOPort smiIO, pm1aIO, pm1bIO;
  150.     public static int Enable() {
  151.         // check if acpi is enabled
  152.  
  153.         if (pm1aIO.Word == 0) {
  154.             // check if acpi can be enabled
  155.             if (SMI_CMD != null && ACPI_ENABLE != 0) {
  156.                 smiIO.Byte = ACPI_ENABLE;
  157.                 //CPUBus.Write8((byte)SMI_CMD, ACPI_ENABLE); // send acpi enable command
  158.                 // give 3 seconds time to enable acpi
  159.                 int i;
  160.                 for (i = 0; i < 300; i++) {
  161.                     if ((pm1aIO.Word & 1) == 1)
  162.                         //if ((CPUBus.Read16((ushort)PM1a_CNT) & SCI_EN) == 1)
  163.                     {
  164.                         break;
  165.                     }
  166.  
  167.                 }
  168.                 if (PM1b_CNT != null)
  169.                     for (; i < 300; i++) {
  170.                         //if ((CPUBus.Read16((ushort)PM1b_CNT) & SCI_EN) == 1)
  171.                         if ((pm1bIO.Word & 1) == 1) {
  172.                             break;
  173.                         }
  174.                     }
  175.                 if (i < 300) {
  176.  
  177.                     return 0;
  178.                 } else {
  179.                     Console.WriteLine("couldn't enable acpi.");
  180.                     return -1;
  181.                 }
  182.             } else {
  183.                 Console.WriteLine("no known way to enable acpi.");
  184.                 return -1;
  185.             }
  186.         } else {
  187.  
  188.             return 0;
  189.         }
  190.     }
  191.     public static void Disable() {
  192.         smiIO.Byte = ACPI_DISABLE;
  193.     }
  194.     public static int Init() {
  195.         byte* ptr = (byte*)RSDPAddress();
  196.         int addr = 0;
  197.  
  198.         for (int i = 19; i >= 16; i--) {
  199.             addr += (*((byte*)ptr + i));
  200.             addr = (i == 16) ? addr : addr << 8;
  201.         }
  202.  
  203.         ptr = (byte*)addr;
  204.         ptr += 4;
  205.         addr = 0;
  206.         for (int i = 3; i >= 0; i--) {
  207.             addr += (*((byte*)ptr + i));
  208.             addr = (i == 0) ? addr : addr << 8;
  209.         }
  210.         int length = addr;
  211.  
  212.         ptr -= 4;
  213.         // check if address is correct  ( if acpi is available on this pc )
  214.         if (ptr != null && acpiCheckHeader((byte*)ptr, "RSDT") == 0) {
  215.             addr = 0;
  216.             // the RSDT contains an unknown number of pointers to acpi tables
  217.  
  218.             int entrys = length;
  219.             entrys = (entrys - 36) / 4;
  220.             ptr += 36;   // skip header information
  221.             byte* yeuse;
  222.  
  223.             while (0 < entrys--) {
  224.                 for (int i = 3; i >= 0; i--) {
  225.                     addr += (*((byte*)ptr + i));
  226.                     addr = (i == 0) ? addr : addr << 8;
  227.                 }
  228.                 yeuse = (byte*)addr;
  229.                 // check if the desired table is reached
  230.                 Facp = (byte*)yeuse;
  231.                 if (Compare("FACP", Facp) == 0) {
  232.                     if (acpiCheckHeader((byte*)facpget(0), "DSDT") == 0) {
  233.                         // search the \_S5 package in the DSDT
  234.                         byte* S5Addr = (byte*)facpget(0) + 36; // skip header
  235.                         int dsdtLength = *(facpget(0) + 1) - 36;
  236.                         while (0 < dsdtLength--) {
  237.                             if (Compare("_S5_", (byte*)S5Addr) == 0) {
  238.                                 break;
  239.                             }
  240.                             S5Addr++;
  241.                         }
  242.                         // check if \_S5 was found
  243.                         if (dsdtLength > 0) {
  244.                             // check for valid AML structure
  245.                             if ((*(S5Addr - 1) == 0x08 || (*(S5Addr - 2) == 0x08 && *(S5Addr - 1) == '\\')) && *(S5Addr + 4) == 0x12) {
  246.                                 S5Addr += 5;
  247.                                 S5Addr += ((*S5Addr & 0xC0) >> 6) + 2;   // calculate PkgLength size
  248.  
  249.                                 if (*S5Addr == 0x0A) {
  250.                                     S5Addr++;    // skip byteprefix
  251.                                 }
  252.                                 SLP_TYPa = (short)(*(S5Addr) << 10);
  253.                                 S5Addr++;
  254.  
  255.                                 if (*S5Addr == 0x0A) {
  256.                                     S5Addr++;    // skip byteprefix
  257.                                 }
  258.                                 SLP_TYPb = (short)(*(S5Addr) << 10);
  259.  
  260.                                 SMI_CMD = facpget(1);
  261.  
  262.                                 ACPI_ENABLE = facpbget(0);
  263.                                 ACPI_DISABLE = facpbget(1);
  264.  
  265.                                 PM1a_CNT = facpget(2);
  266.                                 PM1b_CNT = facpget(3);
  267.  
  268.                                 PM1_CNT_LEN = facpbget(3);
  269.  
  270.                                 SLP_EN = 1 << 13;
  271.                                 SCI_EN = 1;
  272.                                 smiIO = new IOPort((ushort)SMI_CMD);
  273.                                 pm1aIO = new IOPort((ushort)PM1a_CNT);
  274.                                 pm1bIO = new IOPort((ushort)PM1b_CNT);
  275.                                 return 0;
  276.                             } else {
  277.                                 Console.WriteLine("\\_S5 parse error.\n");
  278.                             }
  279.                         } else {
  280.                             Console.WriteLine("\\_S5 not present.\n");
  281.                         }
  282.                     } else {
  283.                         Console.WriteLine("DSDT invalid.\n");
  284.                     }
  285.                 }
  286.                 ptr += 4;
  287.             }
  288.             Console.WriteLine("no valid FACP present.\n");
  289.         } else {
  290.             Console.WriteLine("no acpi.\n");
  291.         }
  292.  
  293.         return -1;
  294.  
  295.     }
  296.  
  297.     public static void Reboot() {
  298.         byte good = 0x02;
  299.         while ((good & 0x02) != 0) {
  300.             good = Inb(0x64);
  301.         }
  302.         Outb(0x64, 0xFE);
  303.  
  304.         Cosmos.Core.Global.CPU.Halt();
  305.     }
  306.  
  307.     static Cosmos.Core.IOPort io = new Cosmos.Core.IOPort(0);
  308.     static int PP = 0, D = 0;
  309.     public static void Outb(ushort port, byte data) {
  310.         if (io.Port != port) {
  311.             io = new Cosmos.Core.IOPort(port);
  312.         }
  313.         io.Byte = data;
  314.         PP = port;
  315.         D = data;
  316.  
  317.     }
  318.     public static byte Inb(ushort port) {
  319.         if (io.Port != port) {
  320.             io = new Cosmos.Core.IOPort(port);
  321.         }
  322.         return io.Byte;
  323.  
  324.     }
  325.  
  326.     public static void Shutdown() {
  327.         // send the shutdown command
  328.         Console.Clear();
  329.         if (PM1a_CNT == null) {
  330.             Init();
  331.         }
  332.         if (pm1aIO != null) {
  333.             pm1aIO.Word = (ushort)(SLP_TYPa | SLP_EN);
  334.             if (PM1b_CNT != null) {
  335.                 pm1bIO.Word = (ushort)(SLP_TYPb | SLP_EN);
  336.             }
  337.  
  338.         }
  339.         //  Console.WriteLine("It is now safe to turn off your computer");
  340.     }
  341. }
  342. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement