225 lines
4.7 KiB
NASM
225 lines
4.7 KiB
NASM
|
|
%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!
|
|
xor ax, ax
|
|
mov ds, ax
|
|
mov [brDrive], dl
|
|
cli
|
|
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, BOOT_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, BOOT_ROOT_SEG
|
|
mov es, bx
|
|
xor bx, bx
|
|
int 0x13
|
|
|
|
;k now read root directory
|
|
mov bx, BOOT_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
|
|
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, BOOT_STAGE2_SEG
|
|
mov es, ax
|
|
|
|
mov ax, [ds:si+26]
|
|
mov bx, BOOT_FAT_SEG
|
|
mov ds, bx ;ds points to beginning of FAT
|
|
xor di, di
|
|
|
|
readstage2_loop:
|
|
cmp ax, 0xff7
|
|
jg readstage2_done
|
|
inc di
|
|
push ax
|
|
call getCHSfromCluster
|
|
mov ax, 0x0201
|
|
mov dl, 0 ;[brDrive]
|
|
xor bx, bx
|
|
int 0x13
|
|
mov bx, es
|
|
add bx, 0x0020
|
|
mov es, bx
|
|
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:BOOT_STAGE2_ADD
|
|
|
|
;------------------------------------------------------
|
|
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
|
|
|