rendered paste body[ORG 0x8000]
start:
mov si, str_loaded
call _puts
;call BtlGetDriveParams
call BtlGetMemoryMap
;load kernel
mov si, str_kern_loading
call _puts
push 6 ;;;; ((0x200 + 0x800) / 0x200) + 1
push 0
push 0
call BtlLoadModule
test ax, ax
jnz .noerr1
mov si, str_err_loadmod
call _puts
jmp BtlPanicRMode
.noerr1:
;load floppy driver
mov si, str_flp_loading
call _puts
push 2
push 0
push 1
call BtlLoadModule
test ax, ax
jnz .noerr2
mov si, str_err_loadmod
call _puts
jmp BtlPanicRMode
.noerr2:
cli
call BtlDisableNMIs
mov ax, 10h
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
lgdt [GDT_DESC]
call BtlEnableA20Line
mov si, str_a20_enabled
call _puts
xchg bx,bx
lidt [IDT_DESC]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 08h:BtlEnterPMode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlPanicRMode:
.rhltloop:
hlt
jmp .rhltloop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlEnableA20Line:
call BtlIoWait
mov al, 0D1h
out 064h, al
call BtlIoWait
mov al, 0DFh ;;;;; A20 enable DFh, 110111[1]1, off DDh, 110111[0]1
out 060h, al
call BtlIoWait
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlDisableNMIs: ;;;
in al, 070h
or al, 080h
out 070h, al
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlEnableNMIs:
in al, 070h
and al, 07Fh
out 070h, al
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlIoWait:
in al, 64h
test al, 2
jnz BtlIoWait
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; INT 13 - DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)
; AH = 08h
; DL = drive (bit 7 set for hard disk)
; ES:DI = 0000h:0000h to guard against BIOS bugs
;Return: CF set on error
; AH = status (07h) (see #00234)
; CF clear if successful
; AH = 00h
; AL = 00h on at least some BIOSes
; BL = drive type (AT/PS2 floppies only) (see #00242)
; CH = low eight bits of maximum cylinder number
; CL = maximum sector number (bits 5-0)
; high two bits of maximum cylinder number (bits 7-6)
; DH = maximum head number
; DL = number of drives
; ES:DI -> drive parameter table (floppies only)
BtlGetDriveParams: ;;;void BtlGetDriveParams(dl:drive_no)
test dl, 80h
jz .is_floppy
push 0 ; ES:DI should be clear for buggy BIOSes,
pop es ; if calling for hard drives
xor di, di
jmp .is_floppy_end
.is_floppy:
push 0 ;;;;;0000:1100h
pop es
mov di, 1100h
.is_floppy_end:
mov ah, 08h
int 13h
jnc .error
mov si, str_err_getdp
call _puts
.error:
mov word [1002h], cx
mov word [1004h], dx
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlGetMemoryMap:
push bp
xor bp, bp
xor ebx, ebx
mov ecx, 20
clc
push 0
pop es
mov di, 1100h
.cont_int15h:
mov eax, 0000E820h
mov edx, 'PAMS'
int 15h
add di, cx
inc bp
test ebx, ebx
jnz .cont_int15h
mov word [1008h], bp
pop bp
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlLoadModule: ;;;int BtlLoadModule([bp+4]:cylinder, [bp+6]:head, [bp+8]:sector)
push bp
mov bp, sp
mov dl, byte [1000h]
mov dh, byte [bp + 6]
mov ax, word [bp + 4]
mov ch, al
mov cl, ah
shl cl, 6
or cx, word [bp + 8]
mov ax, 0201h ; ah = 02 read, al = 01 # sectors
push 0
pop es ;temp buf at 0000:2000
mov bx, 2000h
int 13h
jc .errorz
cmp word [2000h], 'br'
jne .errorz
mov dl, byte [1000h]
mov dh, byte [bp + 6]
mov ax, word [bp + 4]
mov ch, al
mov cl, ah
shl cl, 6
or cx, word [bp + 8]
inc cx ;next sector
mov ax, word [2008h] ;size
shr ax, 9 ;divide by 512
dec ax ;subtract 1 because i already loaded it
mov ah, 2 ;fxn code
mov bx, 2200h ;aha, i had 2000h instead of 2200h
int 13h
jc .errorz
mov cx, word [2008h]
shr cx, 1
push 0
pop ds
mov si, 2000h
mov di, word [200Ch]
mov ax, word [200Eh]
shl ax, 12
push ax
pop es
rep movsw
push 0
pop es
mov ax, 1
mov sp, bp
pop bp
ret 6
.errorz:
push 0
pop es
xor ax, ax
mov sp, bp
pop bp
ret 6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
callint10h:
mov bx, 000Fh
mov ah, 0Eh
int 10h
_puts: ;;;void _puts(si:str)
mov al, byte [si]
inc si
cmp al, 0
jne callint10h
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dumphex: ;;;void dumphex(si:src, bp:len)
movzx di, byte [si]
inc si
mov bx, di
shr bx, 4
mov al, byte [hexstr + bx]
mov ah, 0Eh
mov bx, 000Fh
int 10h
mov bx, di
and bx, 0Fh
mov al, byte [hexstr + bx]
mov ah, 0Eh
mov bx, 0000Fh
int 10h
mov ax, 0E20h
mov bx, 000Fh
int 10h
dec bp
jnz dumphex
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;; PMODE ENTRY POINT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[BITS 32]
align 16, db 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlEnterPMode:
mov ax, 10h
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
;xchg bx,bx
mov byte [0B8000h], 'P'
mov byte [0B8001h], 0x91
call BtlRemapPIC
call BtlEnableNMIs
sti
;1 blue ;5 purple ;9 periwinkle ;d pink
;2 green ;6 orange ;a light green ;e pastel yellow
;3 light blue ;7 reg gray ;b teal ;f white
;4 red ;8 dark gray ;c salmon
call BtlAddImports
mov ebp, 20000h
mov esp, 20000h
mov ebx, 10000h
;lea ebx, [ebx + SECT_CODE * 10h + 10h]
lea ebx, [ebx + 10h]
cmp dword [ebx], 'code'
jne BtlPanicPMode
mov ebx, dword [ebx + 4]
test ebx, ebx
jz BtlPanicPMode
jmp ebx
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlPanicPMode:
.phltloop:
hlt
jmp .phltloop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlAddImports:
;;;;at this point of loading, kernel imports are only supported
;;;get imports for fdc module
mov ebx, 30000h ;base addr of floppy --SHOULD NOT BE CONST FIX FIX
;mov ebx, [ebx + SECT_IMPT * 10h + 10h]
lea ebx, [ebx + 40h] ;;get import table
cmp dword [ebx], 'impt' ;cmp section sig
jne .errorz
mov ebx, dword [ebx + 4] ;goto actual section
mov ecx, dword [ebx] ;get number of libraries... preserve ebx!
add ebx, 4
.loop_top:
test ecx, ecx
jz .done_loop
dec ecx
mov edx, [ebx] ;get library name ptr
cmp dword [edx], 'kern'
jz .cont_loop
cmp word [edx + 4], 'el'
jz .cont_loop ;if not kernel import, continue...
push ecx ;;doing another loop
push ebx
mov ecx, dword [ebx + 4]
mov ebx, dword [ebx + 8]
.loop_top2:
test ecx, ecx
jz .done_loop2
dec ecx
push dword [ebx + 4]
push 10000h
call BtlGetExportAddr
mov [ebx + 8], eax
add ebx, 0Ch
jmp .loop_top2
.done_loop2:
pop ebx
pop ecx
.cont_loop:
add ebx, 0Ch
jmp .loop_top
.done_loop:
.errorz:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlGetExportAddr: ;;target module base addr, name
push ebx
push ecx
mov ebx, dword [esp + 12]
;lea ebx, [eax + SECT_EXPT * 10h + 10h]
lea ebx, [ebx + 50h]
cmp dword [ebx], 'expt'
jne .fail
mov ebx, dword [ebx + 4] ;; ebx = base ptr of export section
mov ecx, dword [ebx]
add ebx, 4
.top_loop:
test ecx, ecx
jz .done_loop
dec ecx
push dword [ebx + 4]
push dword [esp + 16]
call _strcmp
test eax, eax
jnz .not_yet
mov eax, dword [ebx + 8]
pop ecx
pop ebx
ret 8
.not_yet:
add ebx, 0Ch
jmp .top_loop
.done_loop:
.fail:
pop ecx
pop ebx
xor eax, eax
ret 8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_strcmp: ;;;int _strcmp(const char *s1, const char *s2)
push ebx
mov ebx, dword [esp + 4]
mov edx, dword [esp + 8]
.looptop:
mov al, byte [ebx]
test al, al
jz .done
cmp al, byte [edx]
je .nofailyet
pop ebx
mov eax, 1
ret 8
.nofailyet:
inc ebx
inc edx
jmp .looptop
.done:
xor eax, eax
pop ebx
ret 8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlInterrupt00: ;;;;should be an exception trap
push ds
push es
pushad
mov byte [0B8000h], 'I'
mov byte [0B8001h], 015h
mov byte [0B8002h], 'N'
mov byte [0B8003h], 015h
mov byte [0B8004h], 'T'
mov byte [0B8005h], 015h
mov byte [0B8006h], ' '
mov byte [0B8007h], 015h
mov byte [0B8008h], '0'
mov byte [0B8009h], 015h
mov byte [0B800Ah], '!'
mov byte [0B800Bh], 015h
popad
pop es
pop ds
iret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlInterrupt0d:
;push ds
;push es
;pushad
xchg bx, bx
mov byte [0B8000h], 'G'
mov byte [0B8001h], 015h
mov byte [0B8002h], 'P'
mov byte [0B8003h], 015h
mov byte [0B8004h], 'F'
mov byte [0B8005h], 015h
mov byte [0B8006h], ' '
mov byte [0B8007h], 015h
mov byte [0B8008h], '!'
mov byte [0B8009h], 015h
mov byte [0B800Ah], '!'
mov byte [0B800Bh], 015h
;isr13halt:
;jmp isr13halt ;;;;??? EIP CS ???
add esp, 4
;popad ; 0x43 0x821f 0x08 0x10202
;pop es
;pop ds
iret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlIrq00:
mov al, 20h
out 20h, al
iret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlIrq01:
in al, 60h
mov byte [0B8000h], al
mov byte [0B8001h], 015h
mov al, 20h
out 20h, al
iret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlIrq06:
mov al, 20h
out 20h, al
iret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BtlRemapPIC: ;;;void BtlRemapPIC()
in al, 021h ;master
mov cl, al
in al, 0A1h ;slave
mov ch, al
;init
mov al, 011h
out 020h, al
out 080h, al ;wait
out 0A0h, al
out 080h, al
;new pic irq bases
mov al, 020h
out 021h, al
out 080h, al
mov al, 028h
out 0A1h, al
out 080h, al
;continue init
mov al, 4
out 021h, al
out 080h, al
mov al, 2
out 0A1h, al
out 080h, al
mov al, 1
out 021h, al
out 080h, al
out 0A1h, al
out 080h, al
;reset masks
mov al, cl
out 021h, al
mov al, ch
out 0A1h, al
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;; GDT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 8
GDT:
NULL_GDT:
dw 0000h ;limit_low
dw 0000h ;base_low
db 00h ;base_middle
db 00h ;access
db 00h ;granularity
db 00h ;base_high
CS_GDT:
dw 0FFFFh
dw 00h
db 00h
db 10011010b ;cs access: execute/read 9A
db 0CFh
db 00h
DS_GDT:
dw 0FFFFh
dw 00h
db 00h
db 10010010b ;ds access: read/write 92
db 0CFh
db 00h
GDT_DESC:
dw (GDT_DESC - GDT - 1)
dd GDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;; IDT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;struct IDTDescr{
; uint16 offset_1; // offset bits 0..15
; uint16 selector; // a code segment selector in GDT or LDT
; uint8 zero; // unused, set to 0
; uint8 type_attr; // type and attributes, see below
; uint16 offset_2; // offset bits 16..31
;}
align 8
IDT:
;;;; Exceptions
INT00_DESC:
dw BtlInterrupt00
dw 08h
db 00h ;;;pres | priv | sysseg | gatetype
db 10001110b ;;;[1] [00] [0] [1110] (32 bit INT GATE)
dw 0
times 8 * 12 db 0
INT0D_DESC:
dw BtlInterrupt0d
dw 08h
db 00h
db 10001110b
dw 0
times 8 * 18 db 0
;;;; IRQS
INT20_DESC:
dw BtlIrq00
dw 08h
db 00h
db 10001110b
dw 0
IDT_DESC:
dw (IDT_DESC - IDT - 1)
dd IDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;; STRINGS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;strs_floppy_drive_type:
; dd str_fdt_360k ;;0x01
; dd str_fdt_12m ;;0x02
; dd str_fdt_720k ;;0x03
; dd str_fdt_144m ;;0x04
; dd str_fdt_ibm ;;0x05
; dd str_fdt_288m ;;0x06
; dd str_fdt_atapirmd ;;0x10
;str_fdt_360k db '360K', 0
;str_fdt_12m db '1.2M', 0
;str_fdt_720k db '720K', 0
;str_fdt_144m db '1.44M', 0
;str_fdt_ibm db 'Weird IBM', 0
;str_fdt_288m db '2.88M', 0
;str_fdt_atapirmd db 'ATAPI Removable Media Device', 0
str_loaded db 'Stage II Bootloader', 0Dh, 0Ah, 0
str_a20_enabled db 'A20 line enabled', 0Dh, 0Ah, 0
str_kern_loading db 'loading kernel image', 0Dh, 0Ah, 0
str_flp_loading db 'loading floppy driver', 0Dh, 0Ah, 0
str_err_getdp db 'BtlGetDriveParams int 13h ah=8 failed', 0Dh, 0Ah, 0
str_err_loadmod db 'BtlLoadModule failed', 0Dh, 0Ah, 0
hexstr db '0123456789abcdef'
times 0x800-($-$$) db 0