[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