diff --git a/bootdef.inc b/bootdef.inc new file mode 100644 index 0000000..8886336 --- /dev/null +++ b/bootdef.inc @@ -0,0 +1,7 @@ + +%define FAT_SEG 0x07E0 ;right after boot sector +%define ROOT_SEG 0x0900 ;right after FAT +%define STAGE2_SEG 0x0AC0 ;right after ROOT_DIR +%define KERNEL_ADD 0x100000 ;final pmode kernel destination - physical + + diff --git a/kernel.asm b/kernel.asm index 9cf4f4e..b90b24a 100644 --- a/kernel.asm +++ b/kernel.asm @@ -1,10 +1,14 @@ -bits 32 +bits 16 -org 0x100000 +org 0xac00 - mov esi, msg - mov edi, 0xb8000 + mov ax, 0xb800 + mov es, ax + xor ax, ax + mov ds, ax + mov si, msg + xor di, di msg_loop: lodsb diff --git a/stage1.asm b/stage1.asm new file mode 100644 index 0000000..cb8521b --- /dev/null +++ b/stage1.asm @@ -0,0 +1,233 @@ + +%include "bootdef.inc" + +[bits 16] + +org 0x7c00 + + jmp short start + +; -------------------------------------------------- +; data portion of the "DOS BOOT RECORD" +; ---------------------------------------------------------------------- +brINT13Flag DB 90H ; 0002h - 0EH for INT13 AH=42 READ +brOEM DB 'MSDOS5.0' ; 0003h - OEM ID - Windows 95B +brBPS DW 512 ; 000Bh - Bytes per sector +brSPC DB 1 ; 000Dh - Sector per cluster +brSc_b4_fat DW 1 ; 000Eh - Reserved sectors +brFATs DB 2 ; 0010h - FAT copies +brRootEntries DW 0E0H ; 0011h - Root directory entries +brSectorCount DW 2880 ; 0013h - Sectors in volume, < 32MB +brMedia DB 240 ; 0015h - Media descriptor +brSPF DW 9 ; 0016h - Sectors per FAT +brSc_p_trk DW 18 ; 0018h - Sectors per head/track +brHPC DW 2 ; 001Ah - Heads per cylinder +brSc_b4_prt DD 0 ; 001Ch - Hidden sectors +brSectors DD 0 ; 0020h - Total number of sectors +brDrive DB 0 ; 0024h - Physical drive no. + DB 0 ; 0025h - Reserved (FAT32) + DB 29H ; 0026h - Extended boot record sig (FAT32) +brSerialNum DD 404418EAH ; 0027h - Volume serial number +brLabel DB 'HOS 0.1.1 ' ; 002Bh - Volume label +brFSID DB 'FAT12 ' ; 0036h - File System ID +;------------------------------------------------------------------------ + +start: + ;dl=drive number, save it! + mov [brDrive], dl + cli + xor ax, ax + mov ss, ax + mov sp, 0x7Bfe ;right under boot sector + sti + + mov ax, 0xb800 + mov ds, ax + mov es, ax + + xor di, di + mov ax, 0x0700 + mov cx, 2000 +cls: + stosw + loop cls + +enable_a20: + in al, 0x64 + test al, 2 + jnz enable_a20 + mov al, 0xD1 + out 0x64, al +ea20_2: in al, 0x64 + and ax, byte 2 + jnz ea20_2 + mov al, 0xDF + out 0x60, al + +unreal: + xor ax, ax + mov es, ax + mov ds, ax + + lgdt [gdtr] ;load gdt + cli + push es + push ds ;save segment values + mov ebx, cr0 + inc bl + mov cr0, ebx ;pmode! + mov ax, KERNEL_DATA + mov es, ax + mov ds, ax ;load segment limits + dec bl + mov cr0, ebx ;back to real mode! + pop ds + pop es ;segments back, with 4gb limits! + sti + +;now lets read in the FAT and root directory so we can search for the kernel file... + mov ax, 0x0209 ;FAT1 + mov cx, 0x0002 + xor dh, dh + mov dl, [brDrive] + mov bx, FAT_SEG + mov es, bx + xor bx, bx + int 0x13 + + mov ax, 0x020E ;root directory + mov cx, 0x0002 ;cyl/sect + mov dh, 0x01 ;head + mov dl, [brDrive] ;drive + mov bx, ROOT_SEG + mov es, bx + xor bx, bx + int 0x13 + +;k now read root directory + mov bx, ROOT_SEG + mov ds, bx + xor si, si ;k now ds:si points to beginning of root directory + mov es, si + mov cx, 224 ;max root entries +loop_compare: + mov di, stage2 + push cx + push si ;save pointer to root dir entry + mov cx, 11 +loop_name: + cmpsb + loopz loop_name + ;cmp cx, 0 + jnz goon ;cx didn't get to zero, bad file + pop si + pop cx + jmp found_file ;good file, ds:si points to start of root directory entry +goon: + pop si + pop cx + add si, 32 + loop loop_compare + +error: + jmp $ ;halt! no kernel file found! + +found_file: ;ds:si points to root dir entry + mov ax, STAGE2_SEG + mov es, ax + + mov ax, [ds:si+26] + mov bx, FAT_SEG + mov ds, bx ;ds points to beginning of FAT + xor bx, bx + xor di, di + +readstage2_loop: + cmp ax, 0xff7 + jg readstage2_done + inc di + push ax + push bx + call getCHSfromCluster + pop bx + push bx + mov ax, 0x0201 + mov dl, [brDrive] + int 0x13 + pop bx + add bx, 512 + cmp bx, 0 + jne readstage2_goon + mov bx, es + add bx, 0x0100 + mov es, bx + xor bx, bx +readstage2_goon: + pop ax ;current logical cluster # + + mov cx, ax ;cx=logical cluster + mov dx, 3 + mul dx + shr ax, 1 ;ax=logical cluster * 3 / 2 + mov si, ax + test cl, 1 ;is bit0 set? + jnz odd_cluster +even_cluster: + lodsw + and ax, 0x0fff + jmp got_cluster +odd_cluster: + lodsw + shr ax, 4 +got_cluster: + jmp readstage2_loop + +readstage2_done: + + jmp 0:(STAGE2_SEG*16) + +;------------------------------------------------------ +getCHSfromCluster: + ;input: ax=lba of sector on floppy (0-2879) + add ax, 31 ;convert logical cluster# to lba# + xor dx, dx ;lba->chs + mov bx, 18 + div bx + inc dx + mov cl, dl ;sector# (1-18) + xor dx, dx + mov bx, 2 + div bx + mov ch, al ;cylinder# (0-79) + mov dh, dl ;head# (0-1) + ret + + +;------------------------------------------------------- +gdtr: + dw gdt_end-gdt-1 + dd gdt +gdt: + dd 0 + dd 0 + +KERNEL_DATA equ $-gdt + db 0xff ;segment 16 = 4gb data + db 0xff + db 0x00 + db 0x00 + db 0x00 + db 0x92 + db 0xcf ;cf + db 0x00 + +gdt_end: + + + +stage2: db "STAGE2 BIN" + +times 510-($-$$) db 0 + +db 0x55, 0xaa + diff --git a/bootsect.asm b/stage2.asm similarity index 100% rename from bootsect.asm rename to stage2.asm