forked from KolibriOS/kolibrios
418e448f59
git-svn-id: svn://kolibrios.org@4299 a494cfbc-eb01-0410-851d-a64ba20cac60
190 lines
3.4 KiB
NASM
190 lines
3.4 KiB
NASM
; KolibriOS bootloader
|
|
; bootsector for loading from FAT32 flash (or hard) drive
|
|
; intended for use with mtldr_f file in root folder
|
|
; this code has been written by diamond in 2005,2006,2007 specially for KolibriOS
|
|
|
|
; this code is loaded by BIOS to 0000:7C00
|
|
org 0x7C00
|
|
jmp @f
|
|
nop
|
|
times 57h db 0
|
|
; file 'bt2.dat':3,57h
|
|
@@:
|
|
cmp byte [si], 80h
|
|
jnz @f
|
|
mov eax, [si+8]
|
|
mov [cs:7C1Ch], eax
|
|
@@:
|
|
xor eax, eax
|
|
mov ds, ax
|
|
mov ss, ax
|
|
mov sp, 7C00h
|
|
mov bp, sp
|
|
mov [boot_drive], dl
|
|
cld
|
|
sti
|
|
push 800h
|
|
pop es
|
|
movzx ebx, word [bp+0Eh] ; reserved_sect
|
|
mov [fat_start], ebx
|
|
mov al, byte [bp+10h] ; num_fats
|
|
mul dword [bp+24h] ; sect_fat
|
|
add eax, ebx
|
|
; cluster 2 begins from sector eax
|
|
movzx ebx, byte [bp+0Dh] ; sects_per_clust
|
|
add bx, bx
|
|
sub eax, ebx
|
|
mov [data_start], eax
|
|
mov eax, [bp+2Ch] ; root_cluster
|
|
and eax, 0FFFFFFFh
|
|
fat32_parse_dir:
|
|
xor bx, bx
|
|
mov di, bx
|
|
push eax
|
|
call read_cluster
|
|
movzx cx, byte [bp+0Dh] ; sects_per_clust
|
|
shl cx, 4 ; *0x200/0x20
|
|
scan_cluster:
|
|
cmp byte [es:di], 0
|
|
jz file_not_found
|
|
push cx di
|
|
mov cx, 11
|
|
mov si, mtldr_f
|
|
repz cmpsb
|
|
pop di cx
|
|
jz file_found
|
|
add di, 20h
|
|
loop scan_cluster
|
|
pop eax
|
|
call next_cluster
|
|
jnc file_not_found
|
|
jc fat32_parse_dir
|
|
file_found:
|
|
pop eax
|
|
mov ax, [es:di+14h]
|
|
and ax, 0FFFh
|
|
shl eax, 10h
|
|
mov ax, [es:di+1Ah]
|
|
; eax contains first cluster
|
|
@@:
|
|
xor bx, bx
|
|
push eax
|
|
call read_cluster
|
|
mov ax, es
|
|
movzx cx, byte [bp+0Dh]
|
|
shl cx, 5
|
|
add ax, cx
|
|
mov es, ax
|
|
pop eax
|
|
call next_cluster
|
|
jc @b
|
|
jmp 0:8000h
|
|
|
|
file_not_found:
|
|
mov si, file_not_found_msg
|
|
sayerr:
|
|
call out_string
|
|
jmp $
|
|
|
|
read_cluster:
|
|
; in: eax = cluster, bx->buffer
|
|
movzx ecx, byte [bp+0Dh]
|
|
mul ecx
|
|
add eax, [data_start]
|
|
|
|
; read procedure
|
|
; in: eax = absolute sector
|
|
; cx = number of sectors
|
|
; es:bx -> buffer
|
|
read:
|
|
add eax, [bp+1Ch] ; hidden sectors
|
|
push es
|
|
read_loop:
|
|
pushad
|
|
; allocate disk address packet on the stack
|
|
; qword +8: absolute block number
|
|
push 0
|
|
push 0 ; dword +C is high dword
|
|
push eax ; dword +8 is low dword
|
|
; dword +4: buffer address
|
|
push es ; word +6 is segment
|
|
push bx ; word +4 is offset
|
|
; word +2: number of blocks, limited to 7Fh
|
|
sub cx, 7Fh
|
|
sbb ax, ax
|
|
and ax, cx
|
|
add ax, 7Fh
|
|
push ax
|
|
shl ax, 5
|
|
mov cx, es
|
|
add cx, ax
|
|
mov es, cx
|
|
; word +0: size of packet = 10h
|
|
push 10h
|
|
; now pair ss:sp contain address of disk address packet
|
|
mov ax, 4200h
|
|
mov dl, [boot_drive]
|
|
mov si, sp
|
|
int 13h
|
|
mov si, disk_read_err
|
|
jc sayerr
|
|
popaw
|
|
popad
|
|
add eax, 7Fh
|
|
sub cx, 7Fh
|
|
ja read_loop
|
|
pop es
|
|
ret
|
|
|
|
next_cluster:
|
|
push es
|
|
push ds
|
|
pop es
|
|
mov bx, 7E00h
|
|
; sector is 200h bytes long, one entry in FAT occupies 4 bytes
|
|
; => 80h entries in sector
|
|
push eax
|
|
shr eax, 7 ; div 80h
|
|
cmp eax, [fat_cur_sector]
|
|
jz @f
|
|
mov [fat_cur_sector], eax
|
|
add eax, [fat_start]
|
|
mov cx, 1
|
|
call read
|
|
@@:
|
|
pop eax
|
|
and eax, 7Fh
|
|
mov eax, [7E00h+eax*4]
|
|
and eax, 0FFFFFFFh
|
|
cmp eax, 0FFFFFF7h
|
|
mov si, bad_cluster
|
|
jz sayerr
|
|
pop es
|
|
ret
|
|
|
|
out_string:
|
|
lodsb
|
|
test al, al
|
|
jz .xxx
|
|
mov ah, 0Eh
|
|
mov bx, 7
|
|
int 10h
|
|
jmp out_string
|
|
.xxx: ret
|
|
|
|
file_not_found_msg db 'Cannot find file '
|
|
mtldr_f db 'MTLD_F32 '
|
|
db 13,10,0
|
|
disk_read_err db 'Disk read error',13,10,0
|
|
bad_cluster db 'Bad cluster',13,10,0
|
|
fat_cur_sector dd -1
|
|
|
|
times (7DFEh - $) db 0
|
|
db 55h, 0AAh
|
|
|
|
virtual at 7A00h
|
|
fat_start dd ?
|
|
data_start dd ?
|
|
boot_drive db ?
|
|
end virtual
|