362 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			362 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{ ************************************************
 | 
						|
  * Asuro
 | 
						|
  * Unit: util
 | 
						|
  * Description: Utilities for data manipulation
 | 
						|
  ************************************************
 | 
						|
  * Author: K Morris
 | 
						|
  * Contributors: 
 | 
						|
  ************************************************ }
 | 
						|
 | 
						|
unit util;
 | 
						|
 | 
						|
{$ASMMODE intel}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
uses
 | 
						|
    bios_data_area, tracer;
 | 
						|
 | 
						|
function  INTE : boolean;
 | 
						|
procedure CLI();
 | 
						|
procedure STI();
 | 
						|
procedure GPF();
 | 
						|
 | 
						|
function hi(b : uint8) : uint8;
 | 
						|
function lo(b : uint8) : uint8;
 | 
						|
function switchendian(b : uint8) : uint8;
 | 
						|
function getWord(i : uint32; hi : boolean) : uint16;
 | 
						|
function getByte(i : uint32; index : uint8) : uint8;
 | 
						|
 | 
						|
procedure outb(port : uint16; val : uint8);
 | 
						|
procedure outw(port : uint16; val : uint16);
 | 
						|
procedure outl(port : uint16; val : uint32);
 | 
						|
function inb(port : uint16) : uint8;
 | 
						|
function inw(port : uint16) : uint16;
 | 
						|
function inl(port : uint16) : uint32;
 | 
						|
procedure io_wait;
 | 
						|
 | 
						|
procedure memset(location : uint32; value : uint8; size : uint32);
 | 
						|
procedure memcpy(source : uint32; dest : uint32; size : uint32);
 | 
						|
 | 
						|
procedure printmemory(source : uint32; length : uint32; col : uint32; delim : PChar; offset_row : boolean);
 | 
						|
 | 
						|
procedure halt_and_catch_fire();
 | 
						|
procedure halt_and_dont_catch_fire();
 | 
						|
procedure BSOD(fault : pchar; info : pchar);
 | 
						|
procedure psleep(t : uint16);
 | 
						|
 | 
						|
var
 | 
						|
    endptr : uint32; external name '__end';
 | 
						|
    stack  : uint32; external name 'KERNEL_STACK';
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
uses
 | 
						|
    console;
 | 
						|
 | 
						|
function INTE : boolean;
 | 
						|
var
 | 
						|
    flags : uint32;
 | 
						|
begin
 | 
						|
    asm
 | 
						|
        PUSH EAX
 | 
						|
        PUSHF
 | 
						|
        POP EAX
 | 
						|
        MOV flags, EAX
 | 
						|
        POP EAX
 | 
						|
    end;
 | 
						|
    INTE:= (flags AND (1 SHL 9)) > 0;
 | 
						|
end;
 | 
						|
 | 
						|
procedure io_wait;
 | 
						|
var
 | 
						|
    port : uint8;
 | 
						|
    val  : uint8;
 | 
						|
begin
 | 
						|
    port:= $80;
 | 
						|
    val:= 0;
 | 
						|
    asm
 | 
						|
        PUSH EAX
 | 
						|
        PUSH EDX
 | 
						|
        MOV DX, port
 | 
						|
        MOV AL, val
 | 
						|
        OUT DX, AL
 | 
						|
        POP EDX
 | 
						|
        POP EAX   
 | 
						|
    end;  
 | 
						|
end;
 | 
						|
 | 
						|
procedure printmemory(source : uint32; length : uint32; col : uint32; delim : PChar; offset_row : boolean);
 | 
						|
var
 | 
						|
    buf : puint8;
 | 
						|
    i   : uint32;
 | 
						|
 | 
						|
begin   
 | 
						|
    push_trace('util.printmemory');
 | 
						|
    buf:= puint8(source);
 | 
						|
    for i:=0 to length do begin
 | 
						|
        if offset_row and (i = 0) then begin
 | 
						|
            console.writehex(source + (i * col));
 | 
						|
            console.writestring(': ');
 | 
						|
        end; 
 | 
						|
        console.writehexpair(buf[i]);
 | 
						|
        if ((i+1) MOD col) = 0 then begin
 | 
						|
            console.writestringln(' ');  
 | 
						|
            if offset_row then begin
 | 
						|
                console.writehex(source + (i * col));
 | 
						|
                console.writestring(': ');
 | 
						|
            end;  
 | 
						|
        end else begin
 | 
						|
            console.writestring(delim);
 | 
						|
        end;
 | 
						|
    end;
 | 
						|
    console.writestringln(' ');   
 | 
						|
    pop_trace;
 | 
						|
end;
 | 
						|
 | 
						|
function hi(b : uint8) : uint8; [public, alias: 'util_hi'];
 | 
						|
begin
 | 
						|
     hi:= (b AND $F0) SHR 4;
 | 
						|
end;
 | 
						|
 | 
						|
function lo(b : uint8) : uint8; [public, alias: 'util_lo'];
 | 
						|
begin
 | 
						|
     lo:= b AND $0F;
 | 
						|
end;
 | 
						|
 | 
						|
procedure CLI(); assembler; nostackframe;
 | 
						|
asm
 | 
						|
    CLI
 | 
						|
end;
 | 
						|
 | 
						|
procedure STI(); assembler; nostackframe;
 | 
						|
asm
 | 
						|
    STI
 | 
						|
end;
 | 
						|
 | 
						|
procedure GPF(); assembler;
 | 
						|
asm
 | 
						|
    INT 13
 | 
						|
end;
 | 
						|
 | 
						|
function switchendian(b : uint8) : uint8; [public, alias: 'util_switchendian'];
 | 
						|
begin
 | 
						|
     switchendian:= (lo(b) SHL 4) OR hi(b);
 | 
						|
end;
 | 
						|
 | 
						|
procedure psleep(t : uint16);
 | 
						|
var
 | 
						|
    t1, t2 : uint16;
 | 
						|
 | 
						|
begin
 | 
						|
    t1:= BDA^.Ticks;
 | 
						|
    t2:= BDA^.Ticks;
 | 
						|
    while t2-t1 < t do begin
 | 
						|
        t2:= BDA^.Ticks;
 | 
						|
        if t2 < t1 then break;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure outl(port : uint16; val : uint32); [public, alias: 'util_outl'];
 | 
						|
begin
 | 
						|
     asm
 | 
						|
          PUSH EAX
 | 
						|
          PUSH EDX
 | 
						|
          MOV DX, port
 | 
						|
          MOV EAX, val
 | 
						|
          OUT DX, EAX
 | 
						|
          POP EDX
 | 
						|
          POP EAX
 | 
						|
     end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure outw(port : uint16; val : uint16); [public, alias: 'util_outw'];
 | 
						|
begin
 | 
						|
     asm
 | 
						|
          PUSH EAX
 | 
						|
          PUSH EDX
 | 
						|
          MOV DX, port
 | 
						|
          MOV AX, val
 | 
						|
          OUT DX, AX
 | 
						|
          POP EDX
 | 
						|
          POP EAX
 | 
						|
     end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure outb(port : uint16; val : uint8); [public, alias: 'util_outb'];
 | 
						|
begin
 | 
						|
     asm
 | 
						|
          PUSH EAX
 | 
						|
          PUSH EDX
 | 
						|
          MOV DX, port
 | 
						|
          MOV AL, val
 | 
						|
          OUT DX, AL
 | 
						|
          POP EDX
 | 
						|
          POP EAX
 | 
						|
     end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure halt_and_catch_fire(); [public, alias: 'util_halt_and_catch_fire'];
 | 
						|
begin
 | 
						|
     asm
 | 
						|
          cli
 | 
						|
          hlt
 | 
						|
     end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure halt_and_dont_catch_fire(); [public, alias: 'util_halt_and_dont_catch_fire'];
 | 
						|
begin
 | 
						|
    while true do begin
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
function inl(port : uint16) : uint32; [public, alias: 'util_inl'];
 | 
						|
begin
 | 
						|
     asm
 | 
						|
          PUSH EAX
 | 
						|
          PUSH EDX
 | 
						|
          MOV DX, port
 | 
						|
          IN EAX, DX
 | 
						|
          MOV inl, EAX
 | 
						|
          POP EDX
 | 
						|
          POP EAX
 | 
						|
     end;
 | 
						|
end;
 | 
						|
 | 
						|
function inw(port : uint16) : uint16; [public, alias: 'util_inw'];
 | 
						|
begin
 | 
						|
     asm
 | 
						|
          PUSH EAX
 | 
						|
          PUSH EDX
 | 
						|
          MOV DX, port
 | 
						|
          IN AX, DX
 | 
						|
          MOV inw, AX
 | 
						|
          POP EDX
 | 
						|
          POP EAX
 | 
						|
     end;
 | 
						|
end;
 | 
						|
 | 
						|
function inb(port : uint16) : uint8; [public, alias: 'util_inb'];
 | 
						|
begin
 | 
						|
     asm
 | 
						|
          PUSH EAX
 | 
						|
          PUSH EDX
 | 
						|
          MOV DX, port
 | 
						|
          IN AL, DX
 | 
						|
          MOV inb, AL
 | 
						|
          POP EDX
 | 
						|
          POP EAX
 | 
						|
     end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure memset(location : uint32; value : uint8; size : uint32);
 | 
						|
var
 | 
						|
    loc : puint8;
 | 
						|
    i   : uint32;
 | 
						|
 | 
						|
begin
 | 
						|
    push_trace('util.memset');
 | 
						|
    for i:=0 to size-1 do begin
 | 
						|
        loc:= puint8(location + i);
 | 
						|
        loc^:= value;
 | 
						|
    end;
 | 
						|
    pop_trace;
 | 
						|
end;
 | 
						|
 | 
						|
procedure memcpy(source : uint32; dest : uint32; size : uint32);
 | 
						|
var
 | 
						|
    src, dst : puint8;
 | 
						|
    i : uint32;
 | 
						|
 | 
						|
begin
 | 
						|
    push_trace('util.memcpy');
 | 
						|
    for i:=0 to size-1 do begin
 | 
						|
        src:= puint8(source + i);
 | 
						|
        dst:= puint8(dest + i);
 | 
						|
        dst^:= src^;
 | 
						|
    end;
 | 
						|
    pop_trace;
 | 
						|
end;
 | 
						|
 | 
						|
function getWord(i : uint32; hi : boolean) : uint16;
 | 
						|
begin
 | 
						|
    if hi then begin
 | 
						|
        getWord:= (i AND $FFFF0000) SHR 16;
 | 
						|
    end else begin
 | 
						|
        getWord:= (i AND $0000FFFF);
 | 
						|
    end;    
 | 
						|
end;
 | 
						|
 | 
						|
function getByte(i : uint32; index : uint8) : uint8;
 | 
						|
var
 | 
						|
    mask : uint32;
 | 
						|
 | 
						|
begin
 | 
						|
    mask:= ($FF SHL (8*index));
 | 
						|
    getByte:= (i AND mask) SHR (8*index);
 | 
						|
end;
 | 
						|
 | 
						|
procedure BSOD(fault : pchar; info : pchar);
 | 
						|
var
 | 
						|
    trace : pchar;
 | 
						|
    i     : uint32;
 | 
						|
    z     : uint32;
 | 
						|
 | 
						|
begin
 | 
						|
    disable_cursor;
 | 
						|
    if not BSOD_ENABLE then exit;
 | 
						|
    console.setdefaultattribute(console.combinecolors(white, Red));
 | 
						|
    console.clear;
 | 
						|
    console.writestringln(' ');
 | 
						|
    console.writestringln(' ');
 | 
						|
    console.writestring('             ');
 | 
						|
    console.setdefaultattribute(console.combinecolors(black, white));  
 | 
						|
    console.writestring('                                                    ');
 | 
						|
    console.setdefaultattribute(console.combinecolors(white, Red));
 | 
						|
    console.writestringln(' ');
 | 
						|
    console.writestring('             ');
 | 
						|
    console.setdefaultattribute(console.combinecolors(black, white));
 | 
						|
    console.writestring('             ASURO DID A WHOOPSIE!  :(              ');
 | 
						|
    console.setdefaultattribute(console.combinecolors(lwhite, Red));
 | 
						|
    console.writestringln(' ');
 | 
						|
    console.writestring('             ');
 | 
						|
    console.setdefaultattribute(console.combinecolors(black, white));
 | 
						|
    console.writestring('                                                    ');
 | 
						|
    console.setdefaultattribute(console.combinecolors(white, Red));
 | 
						|
    console.writestringln(' ');
 | 
						|
    console.writestringln(' ');
 | 
						|
    console.writestringln(' ');
 | 
						|
    console.writestringln('    Asuro encountered an error and your computer is now a teapot.');
 | 
						|
    console.writestringln(' ');
 | 
						|
    console.writestringln('    Your data is almost certainly safe.');
 | 
						|
    console.writestringln(' ');
 | 
						|
    console.writestringln('    Details of the fault (for those boring enough to read) are as follows: ');
 | 
						|
    console.writestringln(' ');
 | 
						|
    console.writestring('    Fault ID:   ');
 | 
						|
    console.writestringln(fault);
 | 
						|
    console.writestring('    Fault Info: ');
 | 
						|
    console.writestringln(info);
 | 
						|
    console.writestringln(' ');
 | 
						|
    console.writestring('    Call Stack: ');
 | 
						|
    trace:= tracer.get_last_trace;
 | 
						|
    if trace <> nil then begin
 | 
						|
        console.writestring('[-0] ');
 | 
						|
        console.writestringln(trace);
 | 
						|
        for i:=1 to 6 do begin
 | 
						|
            trace:= tracer.get_trace_N(i);
 | 
						|
            if trace <> nil then begin
 | 
						|
                console.writestring('                [');
 | 
						|
                console.writestring('-');
 | 
						|
                console.writeint(i);
 | 
						|
                console.writestring('] ');
 | 
						|
                console.writestringln(trace);
 | 
						|
            end;
 | 
						|
        end;
 | 
						|
    end else begin
 | 
						|
        console.writestringln('Unknown.')
 | 
						|
    end;
 | 
						|
    halt_and_catch_fire();
 | 
						|
end;
 | 
						|
 | 
						|
end.
 |