{ Include->Util - Data Manipulation Utlities. @author(Kieron Morris ) } 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 switchendian16(b : uint16) : uint16; function switchendian32(b : uint32) : uint32; 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 printmemoryWND(source : uint32; length : uint32; col : uint32; delim : PChar; offset_row : boolean; WND : HWND); procedure halt_and_catch_fire(); procedure halt_and_dont_catch_fire(); procedure BSOD(fault : pchar; info : pchar); procedure psleep(t : uint16); procedure sleep(seconds : uint32); function get16bitcounter : uint16; function get32bitcounter : uint32; function get64bitcounter : uint64; function getTSC : uint64; function div6432(dividend : uint64; divisor : uint32) : uint64; function BCDToUint8(bcd : uint8) : uint8; function HexCharToDecimal(hex : char) : uint8; procedure resetSystem(); function getESP : uint32; function MsSinceSystemBoot : uint64; var endptr : uint32; external name '__end'; stack : uint32; external name 'KERNEL_STACK'; implementation uses console, RTC, cpu, serial, strings; function MsSinceSystemBoot : uint64; begin MsSinceSystemBoot:= div6432(getTSC, (CPUID.ClockSpeed.Hz div 1000)); end; function div6432(dividend : uint64; divisor : uint32) : uint64; var d0, d4 : uint32; r0, r4 : uint32; begin d4:= dividend SHR 32; d0:= dividend AND $FFFFFFFF; asm PUSHAD xor edx, edx mov eax, d4 div divisor mov r4, eax mov eax, d0 div divisor mov r0, eax POPAD end; div6432:= (r0 SHL 32) OR r4; end; function switchendian16(b : uint16) : uint16; begin switchendian16:= ((b AND $FF00) SHR 8) OR ((b AND $00FF) SHR 8); end; function switchendian32(b : uint32) : uint32; begin switchendian32:= ((b AND $FF000000) SHR 24) OR ((b AND $00FF0000) SHR 8) OR ((b AND $0000FF00) SHL 8) OR ((b AND $000000FF) SHL 24); end; function getESP : uint32; begin asm MOV getESP, ESP end; end; function HexCharToDecimal(hex : char) : uint8; begin case hex of '0':HexCharToDecimal:=0; '1':HexCharToDecimal:=1; '2':HexCharToDecimal:=2; '3':HexCharToDecimal:=3; '4':HexCharToDecimal:=4; '5':HexCharToDecimal:=5; '6':HexCharToDecimal:=6; '7':HexCharToDecimal:=7; '8':HexCharToDecimal:=8; '9':HexCharToDecimal:=9; 'a':HexCharToDecimal:=10; 'A':HexCharToDecimal:=10; 'b':HexCharToDecimal:=11; 'B':HexCharToDecimal:=11; 'c':HexCharToDecimal:=12; 'C':HexCharToDecimal:=12; 'd':HexCharToDecimal:=13; 'D':HexCharToDecimal:=13; 'e':HexCharToDecimal:=14; 'E':HexCharToDecimal:=14; 'f':HexCharToDecimal:=15; 'F':HexCharToDecimal:=15; else HexCharToDecimal:= 0; end; end; procedure sleep1; var DateTimeStart, DateTimeEnd : TDateTime; begin DateTimeStart:= getDateTime; DateTimeEnd:= DateTimeStart; while DateTimeStart.seconds = DateTimeEnd.seconds do begin DateTimeEnd:= getDateTime; end; end; procedure sleep(seconds : uint32); var i : uint32; begin for i:=1 to seconds do begin sleep1; end; end; 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 printmemoryWND(source : uint32; length : uint32; col : uint32; delim : PChar; offset_row : boolean; WND : HWND); var buf : puint8; i : uint32; begin buf:= puint8(source); for i:=0 to length-1 do begin if offset_row and (i = 0) then begin console.writehexWND(source + (i), WND); console.writestringWND(': ', WND); end; console.writehexpairWND(buf[i], WND); if ((i+1) MOD col) = 0 then begin console.writestringlnWND(' ', WND); if offset_row then begin console.writehexWND(source + (i + 1), WND); console.writestringWND(': ', WND); end; end else begin console.writestringWND(delim, WND); end; end; console.writestringlnWND(' ', WND); end; procedure printmemory(source : uint32; length : uint32; col : uint32; delim : PChar; offset_row : boolean); begin printmemoryWND(source, length, col, delim, offset_row, 0); 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 //serial.sendString('[outl]'); //serial.sendHex(port); //serial.sendHex(val); asm PUSH EAX PUSH EDX MOV DX, port MOV EAX, val OUT DX, EAX POP EDX POP EAX end; io_wait; end; procedure outw(port : uint16; val : uint16); [public, alias: 'util_outw']; begin //serial.sendString('[outw]'); //serial.sendHex(port); //serial.sendHex(val); asm PUSH EAX PUSH EDX MOV DX, port MOV AX, val OUT DX, AX POP EDX POP EAX end; io_wait; end; procedure outb(port : uint16; val : uint8); [public, alias: 'util_outb']; begin //serial.sendString('[outb]'); //serial.sendHex(port); //serial.sendHex(val); asm PUSH EAX PUSH EDX MOV DX, port MOV AL, val OUT DX, AL POP EDX POP EAX end; io_wait; 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 //serial.sendString('[inl]'); //serial.sendHex(port); asm PUSH EAX PUSH EDX MOV DX, port IN EAX, DX MOV inl, EAX POP EDX POP EAX end; io_wait; end; function inw(port : uint16) : uint16; [public, alias: 'util_inw']; begin //serial.sendString('[inw]'); //serial.sendHex(port); asm PUSH EAX PUSH EDX MOV DX, port IN AX, DX MOV inw, AX POP EDX POP EAX end; io_wait; end; function inb(port : uint16) : uint8; [public, alias: 'util_inb']; begin //serial.sendString('[inb]'); //serial.sendHex(port); asm PUSH EAX PUSH EDX MOV DX, port IN AL, DX MOV inb, AL POP EDX POP EAX end; io_wait; 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; function BCDToUint8(bcd : uint8) : uint8; begin BCDToUint8:= ((bcd SHR 4) * 10) + (bcd AND $0F); end; procedure resetSystem(); var good : uint8; begin CLI; good:= $02; while (good AND $02) > 0 do good:= inb($64); outb($64, $FE); halt_and_catch_fire; end; function get16bitcounter : uint16; begin get16bitcounter:= bios_data_area.Counters.c16; end; function get32bitcounter : uint32; begin get32bitcounter:= bios_data_area.Counters.c32; end; function get64bitcounter : uint64; begin get64bitcounter:= bios_data_area.Counters.c64; end; function getTSC : uint64; var hi, lo : uint32; begin asm PUSH EAX PUSH EDX RDTSC MOV hi, EDX MOV lo, EAX POP EDX POP EAX end; getTSC:= (hi SHL 32) OR lo; end; procedure BSOD(fault : pchar; info : pchar); var trace : pchar; i : uint32; z : uint32; begin console.disable_cursor; console.mouseEnabled(false); console.forceQuitAll; if not BSOD_ENABLE then exit; console.setdefaultattribute(console.combinecolors($FFFF, $F800)); console.clear; console.writestringln(' '); console.writestringln(' '); console.writestring(' '); console.setdefaultattribute(console.combinecolors($0000, $FFFF)); console.writestring(' '); console.setdefaultattribute(console.combinecolors($FFFF, $F800)); console.writestringln(' '); console.writestring(' '); console.setdefaultattribute(console.combinecolors($0000, $FFFF)); console.writestring(' ASURO DID A WHOOPSIE! :( '); console.setdefaultattribute(console.combinecolors($FFFF, $F800)); console.writestringln(' '); console.writestring(' '); console.setdefaultattribute(console.combinecolors($0000, $FFFF)); console.writestring(' '); console.setdefaultattribute(console.combinecolors($FFFF, $F800)); 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 tracer.get_trace_count-1 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; console.redrawWindows; halt_and_catch_fire(); end; end.