ACPI checks and poweroff

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
frazzledjazz
Posts: 7
Joined: Tue Mar 03, 2009 3:52 pm

ACPI checks and poweroff

Post by frazzledjazz »

I have the following pulled from C. can someone check it?

Code: Select all

unit acpi.pas:

//

// here is the slighlty complicated ACPI poweroff code

//


uses
	x86,strings;




type





record RSDPtr begin

  Signature:byte=8;

  CheckSum:byte;

  OemID:byte=6;

  Revision:byte;

  ^RsdtAddress:dword;

end;







record FACP begin

  Signature:byte=4;

  Length:dword;

  unneded1:byte=32;

  ^DSDT:dword;

  unneded2:byte=4;

  ^SMI_CMD:dword;

  ACPI_ENABLE:byte;

  ACPI_DISABLE:byte;

  unneded3:byte=10;

  ^PM1a_CNT_BLK:dword;

  ^PM1b_CNT_BLK:dword;

  unneded4:byte=67;

  PM1_CNT_LEN:byte;

end;



var


^SMI_CMD:dword;

ACPI_ENABLE:byte;

ACPI_DISABLE:byte;

^PM1a_CNT:dword;

^PM1b_CNT:dword;

SLP_TYPa:word;

SLP_TYPb:word;

SLP_EN:word;

SCI_EN:word;

PM1_CNT_LEN:byte;



// check if the given address has a valid header

function ^acpiCheckRSDPtr(^ptr:integer);


  ^sig:string;  
  rsdp:rsdPtr;

  bptr:integer;

  check:byte;

  i:integer;



begin
  ^sig:="RSD PTR";
  rsdp := ^ ptr;
  check:=0;

  rsdp:=^ptr
  if (memcmp(sig, rsdp, 8) = 0) then begin 

    // check checksum rsdpd

    bptr := ptr;
    i:=0;  

    repeat 

      check += ^bptr; //huh??

      inc(bptr);
      inc(i);

    until sizeof(rsdp);)  >i



    // found valid rsdpd

    if (check == 0) {

      /*

       if (desc->Revision == 0)

         wrstr("acpi 1");

      else

         wrstr("acpi 2");

      */

      return rsdp->RsdtAddress;

    end;

  end;



  return NULL;

end;







// finds the acpi header and returns the address of the rsdt

procedure ^acpiGetRSDPtr

 

   ^addr:integer;

   ^rsdp:integer;

begin



  // search below the 1mb mark for RSDP signature

    addr = 0x000E0000;
repeat 
    addr += 0x10/sizeof(addr));
{is this inc() or dec() im confused...}
 

    rsdp = acpiCheckRSDPtr(addr);

    if (rsdp != NULL)

      return rsdp;

until addr > 0x00100000;





  // at address 0x40:0x0E is the RM segment of the ebda

  int ebda = *((short *) 0x40E);   // get pointer

  ebda = ebda*0x10 &0x000FFFFF;   // transform segment into linear address



  // search Extended BIOS Data Area for the Root System Description Pointer signature

  for (addr = (unsigned int *) ebda; (int) addr<ebda+1024; addr+= 0x10/sizeof(addr)) {

    rsdp = acpiCheckRSDPtr(addr);

    if (rsdp != NULL)

      return rsdp;

  }



  return NULL;

end;







// checks for a given header and validates checksum

procedure acpiCheckHeader(^ptr:integer; ^sig:char); 

var
   ^checkPtr,len:integer;
   check:char;

begin

  if (memcmp(ptr, sig, 4) = 0) then begin

    ^checkPtr =  ptr;

    len = ^(ptr + 1);

    check = 0;

    while (len >0) do begin 

      check += ^checkPtr; //huh ??

      inc(checkPtr);

    end;

    if (check = 0)

      return 0;

  end;

  return -1;

end;







procedure acpiEnable; 

var
   i:integer;

begin
  // check if acpi is enabled

  if ((readportw (PM1a_CNT) and SCI_EN) = 0) then begin

    // check if acpi can be enabled

    if (SMI_CMD <> 0 & ACPI_ENABLE <> 0) then begin

      writeportb( SMI_CMD, ACPI_ENABLE); // send acpi enable command  --writeportb

      // give 3 seconds time to enable acpi

      i:=0;

      repeat

        if ((readportw( PM1a_CNT) and SCI_EN) = 1) then

          break;

        delay(3000);  //about 3 secs
         inc(i);

      until i > 300;

      if (PM1b_CNT <> 0) then

         i:=0;
      repeat

          if ((readportw( PM1b_CNT) and SCI_EN) = 1) then  //if readportw  () and ()=1

            break;

          delay(3000);
          inc(i);

      until i > 300;

      if (i>300) then begin

        writeln("enabled acpi.");

        return 0;

      end;
      else begin

        writeln("couldn't enable acpi.");

        return -1;

      end;

    else begin

      writeln("no known way to enable acpi.\n");

      return -1;

    end;

  else begin

    writeln("acpi was already enabled.\n");

    return 0;

  end;

end;







//

// bytecode of the \_S5 object

// -----------------------------------------

//        | (optional) |    |    |    |

// NameOP | \          | _  | S  | 5  | _

// 08     | 5A         | 5F | 53 | 35 | 5F

//

// -----------------------------------------------------------------------------------------------------------

//           |           |              | ( SLP_TYPa   ) | ( SLP_TYPb   ) | ( Reserved   ) | (Reserved    )

// PackageOP | PkgLength | NumElements  | byteprefix Num | byteprefix Num | byteprefix Num | byteprefix Num

// 12        | 0A        | 04           | 0A         05  | 0A          05 | 0A         05  | 0A         05

//

//----this-structure-was-also-seen----------------------

// PackageOP | PkgLength | NumElements |

// 12        | 06        | 04          | 00 00 00 00

//

// (Pkglength bit 6-7 encode additional PkgLength bytes [shouldn't be the case here])

//

procedure initAcpi();
var
  ^ptr,entries,dsdtlength:integer;
  ^S5Addr,facp:pointer of char;
  
 begin

   ^ptr = acpiGetRSDPtr();

   

  // check if address is correct  ( if acpi is available on this pc )

  if (ptr <> NULL & acpiCheckHeader(ptr, "RSDT") = 0)then begin 

    // the RSDT contains an unknown number of pointers to acpi tables

    entrys = ^(ptr + 1);

    entrys = (entrys-36) /4;

    ptr += 36/4;   // skip header information



    while (entrys>0) do begin

      // looks like there is a decrement courter weirdly implemented here.
     // check if the desired table is reached

      if (acpiCheckHeader( ^ptr, "FACP") = 0) then begin

        entrys = -2;

        ^facp = ^ptr;  // i think this is right..


        if (acpiCheckHeader(facp->DSDT, "DSDT") = 0) then begin 

          // search the \_S5 package in the DSDT

          ^S5Addr = facp->DSDT +36; // skip header

          dsdtLength= ^(facp->DSDT+1) -36;

          while (dsdtLength >0) do begin 
 // again with the dec counter

            if (memcmp(S5Addr, "_S5_", 4) = 0)

              break;

            inc(S5Addr);

          }

          // check if \_S5 was found

          if (dsdtLength > 0) begin

            // check for valid AML structure

            if ((^(S5Addr-1) = 0x08 or {||} (^(S5Addr-2) == 0x08 and ^(S5Addr-1) = '\\')) and ^(S5Addr+4) = 0x12) then begin

              S5Addr += 5;

              S5Addr += ((^S5Addr &0xC0)>>6) +2;   // calculate PkgLength size   shr(6)?



              if (^S5Addr = 0x0A)

                inc(S5Addr);   // skip byteprefix

              SLP_TYPa = ^(S5Addr)<<10; // shl (10)??

              inc (S5Addr);



              if (^S5Addr = 0x0A)

                inc(S5Addr);   // skip byteprefix

              SLP_TYPb = ^(S5Addr)<<10; //shl(10);



              SMI_CMD = facp->SMI_CMD;



              ACPI_ENABLE = facp->ACPI_ENABLE;

              ACPI_DISABLE = facp->ACPI_DISABLE;



              PM1a_CNT = facp->PM1a_CNT_BLK;

              PM1b_CNT = facp->PM1b_CNT_BLK;



              PM1_CNT_LEN = facp->PM1_CNT_LEN;



              SLP_EN = 1<<13;  // shl(13) ??

              SCI_EN = 1;



              return 0;

            end;
            else begin

              writeln("_S5 parse error.");

            end;

          end;
          else begin

            writeln("_S5 not present.");

          end;

        end;
        else begin

          writeln("DSDT invalid.");

        end;

      end;

      inc(ptr);

    end;

    writeln("no valid FACP present.");

  end;
  else begin

    writeln("no acpi.");

  end;



  return -1;

end;



\



procedure acpiPowerOff;
//did this in assembler thanks to DJ Delorie...  --Jazz
//delorie's code causes triple-fault. we are not powering off.[emu or otherwise]
//only thing i can think as to why is we are not in real mode.

//this is software controlled version with safeguards


 begin

  // SCI_EN is set to 1 if acpi shutdown is possible

  if (SCI_EN = 0)

    return;



  acpiEnable();



  // send the shutdown command

  writeportw(PM1a_CNT, SLP_TYPa | SLP_EN); // what the hell does | (single pipe) mean? there can be only ONE command.

  if (PM1b_CNT <> 0)

    writeportw( PM1b_CNT, SLP_TYPb | SLP_EN);



  writeln("acpi poweroff failed.");

end;

end.{unit}


no, im already certified a 'nut'.thank you.
Last edited by frazzledjazz on Tue Mar 03, 2009 5:03 pm, edited 1 time in total.
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Re: ACPI checks and poweroff

Post by Brynet-Inc »

frazzledjazz wrote:...can someone check me?
..into a psychiatric clinic?

Please use blocks, and.. try formulating complete sentences.
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
JohnnyTheDon
Member
Member
Posts: 524
Joined: Sun Nov 09, 2008 2:55 am
Location: Pennsylvania, USA

Re: ACPI checks and poweroff

Post by JohnnyTheDon »

Correct me if I'm wrong, but isn't there supposed to be code in there?

EDIT: SCROLL FAIL!
Last edited by JohnnyTheDon on Tue Mar 03, 2009 5:50 pm, edited 1 time in total.
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: ACPI checks and poweroff

Post by Troy Martin »

It's easiest to check your code if we know what it does and where you got the original C from.
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
Laksen
Member
Member
Posts: 140
Joined: Fri Nov 09, 2007 3:30 am
Location: Aalborg, Denmark

Re: ACPI checks and poweroff

Post by Laksen »

It doesn't make any sense at all. I would be surprised if it would compile in any compiler
http://j-software.dk | JPasKernel - My Object Pascal kernel
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: ACPI checks and poweroff

Post by Troy Martin »

I think it's written in pascal with a hefty amount of whitespace abuse.
im already certified a 'nut'.thank you.
I now see why.
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
Laksen
Member
Member
Posts: 140
Joined: Fri Nov 09, 2007 3:30 am
Location: Aalborg, Denmark

Re: ACPI checks and poweroff

Post by Laksen »

I think it's written in pascal with a hefty amount of whitespace abuse.
No it's not :roll: It could look like it was, but it isn't valid in any way
http://j-software.dk | JPasKernel - My Object Pascal kernel
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: ACPI checks and poweroff

Post by Troy Martin »

Laksen wrote:
I think it's written in pascal with a hefty amount of whitespace abuse.
No it's not :roll: It could look like it was, but it isn't valid in any way

Code: Select all

unit acpi.pas
I assume that means it's written in pascal. :roll:
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
Laksen
Member
Member
Posts: 140
Joined: Fri Nov 09, 2007 3:30 am
Location: Aalborg, Denmark

Re: ACPI checks and poweroff

Post by Laksen »

Troy Martin wrote:
Laksen wrote:
I think it's written in pascal with a hefty amount of whitespace abuse.
No it's not :roll: It could look like it was, but it isn't valid in any way

Code: Select all

unit acpi.pas
I assume that means it's written in pascal. :roll:
No.. There's so many syntax errors that it isn't even funny. Trust me, I'm an expert pascal programmer :)
http://j-software.dk | JPasKernel - My Object Pascal kernel
Post Reply