cheat-engine/dbvm/bootsector/bootloader.asm
2018-02-20 13:08:24 +01:00

342 lines
5.1 KiB
NASM
Executable file

;16-bit bootsector
;this will load the bigger loader to address 3000:0000
;
BITS 16
GLOBAL main
;SECTION .text
main:
jmp short loader ;0-1
nop ;2
OEMName: db 'CETC2.1' ;3-9
dw 0 ;a-b (set by make)
dw 0 ;c-d (set by make)
bootdrive: db 0 ;e (set during boot)
bootdrive2: db 0 ;f (set by installer)
userdefinedbootdrive: db 0; 10 (set by installer, when set to 1 bootdrive2 is used instead of bootdrive+1 or if from floppy/cd 0x80)
runwithoutmenu: db 0; 11 (set by installer, when set to 1 the menu will be skipped)
db 0 ;12
dw 0x00 ;13-14
db 0; 0xf8 15
dw 0x0000 ;16-17
SPT: dw 62 ;18-19 for some reason my system won'y boot up with these missing so:
NOH: dw 65 ;1a-1b
;----------------------
SectorsPerTrack: dw 0
NumberOfHeads: dw 0
NumberOfCylinders: dw 0
currenttracksector: dw 0x2
currenthead: dw 0
loader:
;cflush
wbinvd
mov [cs:0x7000],eax
mov ax,ds
mov [cs:0x7024],ax
xor ax,ax
mov ds,ax
mov [0x7004],ebx
mov [0x7008],ecx
mov [0x700c],edx
mov [0x7010],esi
mov [0x7014],edi
mov [0x7018],ebp
mov [0x701c],esp
mov ax,ss
mov [0x7022],ax
mov ax,es
mov [0x7026],ax
mov ax,fs
mov [0x7028],ax
mov ax,gs
mov [0x702a],ax
pushf
pop ax
mov [0x702c],ax
cli
sgdt [0x7030]
mov eax,cr0
mov [start_CR0],eax
;setup gs segment
mov ax,0xb800
mov gs,ax
;basic initialization
mov ax,3000h
mov es,ax ;destination to 0x3000
mov ax,cs
mov ds,ax ;make sure data segment points to here
mov [bootdrive],dl ;store the bootdrive register in ds:[bootdrive] (so local segment)
xor ax,ax
mov ss,ax ;might as well setup a place for the stack (0:7bf0)
mov sp,0x3ff0
call zeroUsableMemory
call clearscreen
mov si,msg
call writeline
sti
push es
push ds
;reset disk
mov ax,0
int 13h
;get disk info
push es ;old version of bochs bypass
mov ax,0x6000
mov es,ax
mov di,0
mov ax,0800h
int 13h
pop es ;older version of bochs bug bypass (too lazy to recompile)
inc dh
mov [NumberOfHeads],dh
mov ax,cx
and ax,3fh
inc ax
mov [SectorsPerTrack],ax
mov al,ch
shr ch,6
mov ah,ch
mov [NumberOfCylinders],ah ;not used, but store it anyhow just for the fun of it
mov cx,(size/512)+1 ; number of sectors to read
mov bx,0x0000 ;offset to store at
;now read the vmloader program from the disk to 3000:0000+)
push cx
reader:
mov ax,0x0201 ;read 1 sector
mov cx,[currenttracksector] ;track/sector
mov dh,[currenthead]
mov dl,[bootdrive] ; set dl to the bootdrive
clc
int 13h
sti ;some bioses may disable this on return
jnc reader_ok
reader_err:
mov ah,0
mov dl,[bootdrive]
int 13h
jmp reader
reader_ok:
;successfull read, adjust parameters for next sector
add bx,512 ;place to store at
cmp bx,0
jne checksector
;overflow, vmloader has become bigger than 64KB, we need a new segment (0x40000?)
mov bx,es
add bx,0x1000 ;to the next free segment, 0x3000->0x4000->0x5000
mov es,bx
xor bx,bx
checksector:
;sector
mov dx,[currenttracksector]
inc dl
mov [currenttracksector],dx
push bx
mov bl,'.'
call writechar
pop bx
cmp dl,[SectorsPerTrack]
jb adjusted_currentsector
mov dl,1
mov [currenttracksector],dx
;head
inc byte [currenthead]
mov dl,[currenthead]
cmp dl,[NumberOfHeads]
jne adjusted_head
mov byte [currenthead],0
;cylinder
inc dh
mov [currenthead],dx
adjusted_head:
adjusted_currentsector:
;check if done
pop cx
dec cx
cmp cx,0
push cx
jne reader
pop cx
pop ds
pop es
done:
mov dl,[bootdrive] ;just to be sure
mov dword [0x7c00],0 ;location of lock (0=free)
inc byte [currentline]
;done
jmp 3000h:0000h ;0x30000
currentline: db 0
currentcolumn: dw 0
writechar:
push ax
mov al,80
mul byte [currentline] ;ax = al*currentline (80*currentline)
add ax,[currentcolumn]
shl ax,1 ;multiply ax with 2
xchg ax,di
;ax=currentcolumn*currentline*2
mov byte [gs:di],bl
mov byte [gs:di+1],12
xchg ax,di
pop ax
inc word [currentcolumn]
ret
writeline:
mov ah,160
mov al,[currentline]
mul ah
mov di,ax
writeline_loop:
cmp byte [si],0
je writeline_done
mov al,[si]
mov [gs:di],al
mov byte [gs:di+1],15
add di,2
inc si
jmp writeline_loop
writeline_done:
inc byte [currentline]
ret
clearscreen:
push es
push gs
pop es
push cx
mov cx,2*80*25 / 4
rep stosd
pop cx
pop es
ret
zeroUsableMemory:
push es
pusha
xor ax,ax
int 0x12 ;get low memory size in KB
test ax,ax
je zeroUsabeMemory_error
cmp ax,0x86
je zeroUsabeMemory_error
cmp ax,0x80
je zeroUsabeMemory_error
jmp zeroUsabeMemory_start
zeroUsabeMemory_error:
mov ax,600 ;just guess...
zeroUsabeMemory_start:
sub ax,64 ;take out 64KB as the wipe starts at 0x10000
xchg bx,ax
xor eax,eax
mov si,0x1000
zeroUsableMemory_clear:
mov es,si
mov cx,(0x1000/4)
xor di,di
rep stosd
add si,0x1000
sub bx,64
jnb zeroUsableMemory_clear
popa
pop es
ret
msg:
db 'DBVM BS',0
times 506-($-$$) db 0 ; Pad to 509 bytes
start_CR0:
dd 0 ; storage location of original CR0
BootSignature:
dw 0aa55h ; BootSector signature ; 512 bytes