mirror of
https://github.com/KolibriOS/kolibrios.git
synced 2024-12-12 09:57:05 +03:00
853 lines
17 KiB
NASM
853 lines
17 KiB
NASM
|
; KolibriOS bootloader
|
||
|
; this code has been written by diamond in 2005,2006,2008 specially for KolibriOS
|
||
|
|
||
|
; this code is loaded by ntldr to 0D00:0000
|
||
|
; and by io.sys from config.sys to xxxx:0100
|
||
|
; and by bootmgr in vista to 0000:7C00
|
||
|
format binary
|
||
|
use16
|
||
|
|
||
|
org 0xD000
|
||
|
; entry point for 9x and Vista booting
|
||
|
call @f
|
||
|
; db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd'
|
||
|
db 'NTFS'
|
||
|
@@:
|
||
|
pop si
|
||
|
sub si, 3
|
||
|
cmp si, 7C00h
|
||
|
jz boot_vista
|
||
|
mov si, load_question + 100h - 0D000h
|
||
|
call out_string
|
||
|
; mov si, answer + 100h - 0D000h ; already is
|
||
|
xxy: mov ah, 0
|
||
|
int 16h
|
||
|
or al, 20h
|
||
|
mov [si], al
|
||
|
cmp al, 'y'
|
||
|
jz xxz
|
||
|
cmp al, 'n'
|
||
|
jnz xxy
|
||
|
; continue load Windows
|
||
|
; call out_string
|
||
|
; ret
|
||
|
out_string:
|
||
|
lodsb
|
||
|
test al, al
|
||
|
jz .xxx
|
||
|
mov ah, 0Eh
|
||
|
mov bx, 7
|
||
|
int 10h
|
||
|
jmp out_string
|
||
|
.xxx: ret
|
||
|
xxz:
|
||
|
; boot KolibriOS
|
||
|
call out_string
|
||
|
push 0
|
||
|
pop ds
|
||
|
mov word [4], new01handler + 100h - 0D000h
|
||
|
mov [6], cs
|
||
|
pushf
|
||
|
pop ax
|
||
|
or ah, 1
|
||
|
push ax
|
||
|
popf
|
||
|
; int 19h
|
||
|
; pushf ; there will be no iret
|
||
|
call far [19h*4]
|
||
|
xxt:
|
||
|
; TF has been cleared when entered new01handler
|
||
|
; pushf
|
||
|
; pop ax
|
||
|
; and ah, not 1
|
||
|
; push ax
|
||
|
; popf
|
||
|
xor di, di
|
||
|
mov ds, di
|
||
|
cmp word [8*4+2], 0F000h
|
||
|
jz @f
|
||
|
les bx, [8*4]
|
||
|
mov eax, [es:bx+1]
|
||
|
mov [8*4], eax
|
||
|
@@:
|
||
|
mov si, 100h
|
||
|
boot_vista:
|
||
|
push cs
|
||
|
pop ds
|
||
|
push 0D00h
|
||
|
pop es
|
||
|
mov cx, 2000h/2
|
||
|
rep movsw
|
||
|
jmp 0D00h:0256h
|
||
|
load_question db 'Load KolibriOS? [y/n]: ',0
|
||
|
answer db ?
|
||
|
db 13,10,0
|
||
|
|
||
|
new01handler:
|
||
|
; [sp]=ip, [sp+2]=cs, [sp+4]=flags
|
||
|
push bp
|
||
|
mov bp, sp
|
||
|
push bx
|
||
|
push ds
|
||
|
lds bx, [bp+2]
|
||
|
cmp word [bx], 19cdh
|
||
|
jz xxt
|
||
|
pop ds
|
||
|
pop bx
|
||
|
pop bp
|
||
|
iret
|
||
|
|
||
|
relative_read:
|
||
|
add eax, [partition_start]
|
||
|
|
||
|
; read from hard disk
|
||
|
; drive_size must be already initialized
|
||
|
; in: eax = absolute sector
|
||
|
; cx = number of sectors
|
||
|
; es:bx -> buffer
|
||
|
read:
|
||
|
pushad
|
||
|
cmp eax, [drive_size]
|
||
|
jb .old_style
|
||
|
; new style - LBA, function 42
|
||
|
cmp [has_lba], 0
|
||
|
jz disk_error
|
||
|
; allocate disk address packet on the stack
|
||
|
; qword +8: absolute block number
|
||
|
push dword 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 = 1
|
||
|
; word +0: size of packet = 10h
|
||
|
push dword 10010h
|
||
|
; now pair ss:sp contain address of disk address packet
|
||
|
.patch1:
|
||
|
mov ax, 4200h
|
||
|
mov dl, [boot_drive]
|
||
|
mov si, sp
|
||
|
push ds
|
||
|
push ss
|
||
|
pop ds
|
||
|
int 13h
|
||
|
pop ds
|
||
|
add sp, 10h
|
||
|
.end:
|
||
|
popad
|
||
|
jc disk_error
|
||
|
add bx, 200h
|
||
|
inc eax
|
||
|
dec cx
|
||
|
jnz read
|
||
|
ret
|
||
|
.old_style:
|
||
|
; old style - CHS, function 2
|
||
|
; convert absolute sector in eax to cylinder-head-sector coordinates
|
||
|
; calculate sector
|
||
|
xor edx, edx
|
||
|
movzx ecx, [sectors]
|
||
|
div ecx
|
||
|
; sectors are counted from 1
|
||
|
inc dx
|
||
|
mov cl, dl ; low 6 bits of cl = sector number
|
||
|
; calculate head number
|
||
|
shld edx, eax, 10h ; convert eax to dx:ax
|
||
|
div [heads]
|
||
|
mov dh, dl ; dh = head
|
||
|
mov ch, al ; ch = low 8 bits of cylinder
|
||
|
shl ah, 6
|
||
|
or cl, ah ; high 2 bits of cl = high 2 bits of cylinder
|
||
|
.patch2:
|
||
|
mov ax, 201h ; function 2, al=1 - number of sectors
|
||
|
mov dl, [boot_drive]
|
||
|
int 13h
|
||
|
jmp .end
|
||
|
|
||
|
disk_error:
|
||
|
mov si, disk_error_msg
|
||
|
call out_string
|
||
|
jmp $
|
||
|
|
||
|
has_lba db 0
|
||
|
|
||
|
disk_error_msg db 'Disk read error!',0
|
||
|
start_msg db 2,' KolibriOS bootloader',13,10,0
|
||
|
part_msg db 'looking at partition '
|
||
|
part_char db '0' ; will be incremented before writing message
|
||
|
db ' ... ',0
|
||
|
errfs_msg db 'unknown filesystem',13,10,0
|
||
|
fat16_msg db 'FAT12/FAT16 - unsupported',13,10,0
|
||
|
fat32_msg db 'FAT32'
|
||
|
newline db 13,10,0
|
||
|
ntfs_msg db 'NTFS',13,10,0
|
||
|
error_msg db 'Error'
|
||
|
colon db ': ',0
|
||
|
mft_string db 'MFT',0
|
||
|
root_string db '\',0
|
||
|
noindex_string db '$INDEX_ROOT not found',0
|
||
|
invalid_read_request_string db 'cannot read attribute',0
|
||
|
nodata_string db '$DATA '
|
||
|
notfound_string db 'not found',0
|
||
|
directory_string db 'is a directory',0
|
||
|
notdir_string db 'not a directory',0
|
||
|
fragmented_string db 'too fragmented file',0
|
||
|
exmem_string db 'extended memory error',0
|
||
|
bad_cluster_string db 'bad cluster',0
|
||
|
data_error_msg db 'data error',0
|
||
|
|
||
|
; init procedure - ntldr jmps here
|
||
|
repeat 0D256h - $
|
||
|
db 1
|
||
|
end repeat
|
||
|
start:
|
||
|
; cs=es=0D00, ds=07C0, ss=0
|
||
|
; esi=edi=ebp=0, esp=7C00
|
||
|
xor ax, ax
|
||
|
mov ds, ax
|
||
|
mov es, ax
|
||
|
; our stack is 4Kb-512b-2b!!! (0xDFE)
|
||
|
mov ss, ax
|
||
|
mov esp, 0FFFEh
|
||
|
|
||
|
; we are booting from hard disk identified by [boot_drive]
|
||
|
mov dl, [boot_drive]
|
||
|
cld
|
||
|
sti
|
||
|
; calculate drive size
|
||
|
mov ah, 8 ; 8 = get drive parameters
|
||
|
int 13h
|
||
|
; now: CF is set on error;
|
||
|
; ch = low 8 bits of maximum cylinder number
|
||
|
; cl : low 6 bits makes maximum sector number, high 2 bits are high 2 bits of maximum cylinder number
|
||
|
; dh = maximum head number
|
||
|
jnc @f
|
||
|
mov cx, -1
|
||
|
mov dh, cl
|
||
|
@@:
|
||
|
movzx ax, dh
|
||
|
inc ax
|
||
|
; ax = number of heads
|
||
|
mov [heads], ax
|
||
|
mov dl, cl
|
||
|
and dx, 3Fh
|
||
|
; dx = number of sectors
|
||
|
; (note that sectors are counted from 1, and maximum sector number = number of sectors)
|
||
|
mov [sectors], dx
|
||
|
mul dx
|
||
|
xchg cl, ch
|
||
|
shr ch, 6
|
||
|
inc cx
|
||
|
; cx = number of cylinders
|
||
|
mov [cyls], cx
|
||
|
mul cx
|
||
|
mov word [drive_size], ax
|
||
|
mov word [drive_size+2], dx
|
||
|
; this drive supports LBA?
|
||
|
mov dl, [boot_drive]
|
||
|
mov ah, 41h
|
||
|
mov bx, 55AAh
|
||
|
int 13h
|
||
|
jc .no_lba
|
||
|
cmp bx, 0AA55h
|
||
|
jnz .no_lba
|
||
|
test cl, 1
|
||
|
jz .no_lba
|
||
|
inc [has_lba]
|
||
|
.no_lba:
|
||
|
; say hi to user
|
||
|
mov si, start_msg
|
||
|
call out_string
|
||
|
; now read first sector to determine file system type
|
||
|
; first sector of disk is MBR sector
|
||
|
xor eax, eax
|
||
|
new_partition_ex:
|
||
|
mov cx, 1
|
||
|
mov bx, 0F000h
|
||
|
call read
|
||
|
new_partition:
|
||
|
mov bx, [cur_partition_ofs]
|
||
|
mov al, [bx+4] ; partition type
|
||
|
test al, al
|
||
|
jz next_partition
|
||
|
cmp al, 5
|
||
|
jz @f
|
||
|
cmp al, 0xF
|
||
|
jnz not_extended
|
||
|
@@:
|
||
|
; extended partition
|
||
|
mov eax, [bx+8] ; partition start
|
||
|
add eax, [extended_part_start]
|
||
|
mov [extended_part_cur], eax
|
||
|
next_partition:
|
||
|
add [cur_partition_ofs], 10h
|
||
|
cmp [cur_partition_ofs], 0xF1FE
|
||
|
jb new_partition
|
||
|
mov eax, [extended_part_cur]
|
||
|
test eax, eax
|
||
|
jz partitions_done
|
||
|
cmp [extended_part_start], 0
|
||
|
jnz @f
|
||
|
mov [extended_part_start], eax
|
||
|
@@:
|
||
|
mov [extended_parent], eax
|
||
|
and [extended_part_cur], 0
|
||
|
mov [cur_partition_ofs], 0xF1BE
|
||
|
jmp new_partition_ex
|
||
|
partitions_done:
|
||
|
mov si, total_kaput
|
||
|
call out_string
|
||
|
jmp $
|
||
|
not_extended:
|
||
|
mov eax, [bx+8]
|
||
|
add eax, [extended_parent]
|
||
|
mov [partition_start], eax
|
||
|
push ax
|
||
|
mov si, part_msg
|
||
|
inc [si+part_char-part_msg]
|
||
|
call out_string
|
||
|
pop ax
|
||
|
mov cx, 1
|
||
|
mov bx, 500h
|
||
|
call read
|
||
|
movzx ax, byte [50Dh]
|
||
|
mov [sect_per_clust], ax
|
||
|
; determine file system
|
||
|
cmp dword [536h], 'FAT1'
|
||
|
jz fat1x
|
||
|
cmp dword [552h], 'FAT3'
|
||
|
jz fat32
|
||
|
cmp dword [503h], 'NTFS'
|
||
|
jz ntfs
|
||
|
mov si, errfs_msg
|
||
|
call out_string
|
||
|
jmp next_partition
|
||
|
fat1x:
|
||
|
mov si, fat16_msg
|
||
|
call out_string
|
||
|
jmp next_partition
|
||
|
fat32:
|
||
|
mov si, fat32_msg
|
||
|
call out_string
|
||
|
movzx eax, word [50Bh] ; bytes_per_sect
|
||
|
movzx ebx, byte [50Dh] ; sects_per_clust
|
||
|
mul ebx
|
||
|
mov [cluster_size], eax
|
||
|
movzx ebx, word [50Eh] ; reserved_sect
|
||
|
mov [fat_start], ebx
|
||
|
movzx eax, byte [510h] ; num_fats
|
||
|
mul dword [524h] ; sect_fat
|
||
|
add eax, ebx
|
||
|
; cluster 2 begins from sector eax
|
||
|
movzx ebx, byte [50Dh] ; sects_per_clust
|
||
|
sub eax, ebx
|
||
|
sub eax, ebx
|
||
|
mov [data_start], eax
|
||
|
; parse image name
|
||
|
mov eax, [52Ch] ; root_cluster
|
||
|
mov [cur_obj], root_string
|
||
|
.parsedir:
|
||
|
push ax
|
||
|
mov si, [imgnameofs]
|
||
|
push si
|
||
|
@@:
|
||
|
lodsb
|
||
|
cmp al, 0
|
||
|
jz @f
|
||
|
cmp al, '\'
|
||
|
jnz @b
|
||
|
dec si
|
||
|
mov [missing_slash], si
|
||
|
inc si
|
||
|
@@:
|
||
|
xchg ax, [esp+2]
|
||
|
mov byte [si-1], 0
|
||
|
mov [imgnameofs], si
|
||
|
call fat32_parse_dir
|
||
|
call restore_slash
|
||
|
pop cx
|
||
|
test cl, cl
|
||
|
jz .end
|
||
|
test byte [di+0Bh], 10h
|
||
|
mov si, notdir_string
|
||
|
jz find_error_si
|
||
|
jmp .parsedir
|
||
|
.end:
|
||
|
test byte [di+0Bh], 10h
|
||
|
mov si, directory_string
|
||
|
jnz find_error_si
|
||
|
; parse FAT chunk
|
||
|
; runlist at 2000:0000
|
||
|
mov di, 5
|
||
|
push 2000h
|
||
|
pop es
|
||
|
mov byte [es:di-5], 1 ; of course, non-resident
|
||
|
mov dword [es:di-4], 1
|
||
|
stosd
|
||
|
.parsefat:
|
||
|
push es
|
||
|
push ds
|
||
|
pop es
|
||
|
call next_cluster
|
||
|
pop es
|
||
|
jnc .done
|
||
|
mov ecx, [es:di-8]
|
||
|
add ecx, [es:di-4]
|
||
|
cmp eax, ecx
|
||
|
jz .contc
|
||
|
mov dword [es:di], 1
|
||
|
scasd
|
||
|
stosd
|
||
|
jmp .parsefat
|
||
|
.contc:
|
||
|
inc dword [es:di-8]
|
||
|
jmp .parsefat
|
||
|
.done:
|
||
|
xor eax, eax
|
||
|
stosd
|
||
|
jmp read_img_file
|
||
|
|
||
|
ntfs:
|
||
|
mov si, ntfs_msg
|
||
|
call out_string
|
||
|
movzx eax, word [50Bh] ; bpb_bytes_per_sect
|
||
|
push eax
|
||
|
movzx ebx, byte [50Dh] ; bpb_sects_per_clust
|
||
|
mul ebx
|
||
|
mov [cluster_size], eax
|
||
|
mov [data_start], 0
|
||
|
mov ecx, [540h] ; frs_size
|
||
|
cmp cl, 0
|
||
|
jg .1
|
||
|
neg cl
|
||
|
xor eax, eax
|
||
|
inc eax
|
||
|
shl eax, cl
|
||
|
jmp .2
|
||
|
.1:
|
||
|
mul ecx
|
||
|
.2:
|
||
|
mov [frs_size], eax
|
||
|
pop ebx
|
||
|
xor edx, edx
|
||
|
div ebx
|
||
|
mov [frs_sectors], ax
|
||
|
; read first MFT record - description of MFT itself
|
||
|
mov [cur_obj], mft_string
|
||
|
movzx eax, byte [50Dh] ; bpb_sects_per_clust
|
||
|
mul dword [530h] ; mft_cluster
|
||
|
mov cx, [frs_sectors]
|
||
|
mov bx, 4000h
|
||
|
mov di, bx
|
||
|
push bx
|
||
|
call relative_read
|
||
|
call restore_usa
|
||
|
; scan for unnamed $DATA attribute
|
||
|
pop di
|
||
|
mov ax, 80h ; $DATA
|
||
|
mov bx, 700h
|
||
|
call load_attr
|
||
|
mov si, nodata_string
|
||
|
jc find_error_si
|
||
|
mov [free], bx
|
||
|
; load kolibri.img
|
||
|
; parse image name
|
||
|
mov eax, 5 ; root cluster
|
||
|
mov [cur_obj], root_string
|
||
|
.parsedir:
|
||
|
push ax
|
||
|
mov si, [imgnameofs]
|
||
|
push si
|
||
|
@@:
|
||
|
lodsb
|
||
|
cmp al, 0
|
||
|
jz @f
|
||
|
cmp al, '\'
|
||
|
jnz @b
|
||
|
dec si
|
||
|
mov [missing_slash], si
|
||
|
inc si
|
||
|
@@:
|
||
|
xchg ax, [esp+2]
|
||
|
mov byte [si-1], 0
|
||
|
mov [imgnameofs], si
|
||
|
call ntfs_parse_dir
|
||
|
call restore_slash
|
||
|
pop cx
|
||
|
test cl, cl
|
||
|
jnz .parsedir
|
||
|
read_img_file:
|
||
|
xor si, si
|
||
|
push es
|
||
|
pop fs
|
||
|
; yes! Now read file to 0x100000
|
||
|
lods byte [fs:si]
|
||
|
cmp al, 0 ; assume nonresident attr
|
||
|
mov si, invalid_read_request_string
|
||
|
jz find_error_si
|
||
|
mov si, 1
|
||
|
xor edi, edi
|
||
|
; read buffer to 1000:0000 and move it to extended memory
|
||
|
push 1000h
|
||
|
pop es
|
||
|
xor bx, bx
|
||
|
.img_read_block:
|
||
|
lods dword [fs:si] ; eax=length
|
||
|
xchg eax, ecx
|
||
|
jecxz .img_read_done
|
||
|
lods dword [fs:si] ; eax=disk cluster
|
||
|
.img_read_cluster:
|
||
|
pushad
|
||
|
; read part of file
|
||
|
movzx ecx, byte [50Dh]
|
||
|
mul ecx
|
||
|
add eax, [data_start]
|
||
|
call relative_read
|
||
|
; move it to extended memory
|
||
|
mov ah, 87h
|
||
|
mov ecx, [cluster_size]
|
||
|
push ecx
|
||
|
shr cx, 1
|
||
|
mov si, movedesc
|
||
|
push es
|
||
|
push ds
|
||
|
pop es
|
||
|
int 15h
|
||
|
pop es
|
||
|
test ah, ah
|
||
|
mov si, exmem_string
|
||
|
jnz find_error_si
|
||
|
pop ecx
|
||
|
add [dest_addr], ecx
|
||
|
popad
|
||
|
inc eax
|
||
|
loop .img_read_cluster
|
||
|
jmp .img_read_block
|
||
|
.img_read_done:
|
||
|
; kolibri.img loaded; now load kernel.mnt
|
||
|
load_kernel:
|
||
|
push ds
|
||
|
pop es
|
||
|
mov [cur_obj], kernel_mnt_name
|
||
|
; read boot sector
|
||
|
xor eax, eax
|
||
|
mov bx, 500h
|
||
|
mov cx, 1
|
||
|
call read_img
|
||
|
; init vars
|
||
|
mov ax, [50Eh] ; reserved_sect
|
||
|
add ax, [51Ch] ; hidden
|
||
|
mov word [fat_start], ax
|
||
|
xchg ax, bx
|
||
|
movzx ax, byte [510h] ; num_fats
|
||
|
mul word [516h] ; fat_length
|
||
|
add ax, bx
|
||
|
; read root dir
|
||
|
mov bx, 700h
|
||
|
mov cx, [511h] ; dir_entries
|
||
|
add cx, 0Fh
|
||
|
shr cx, 4
|
||
|
call read_img
|
||
|
add ax, cx
|
||
|
mov [img_data_start], ax
|
||
|
shl cx, 9
|
||
|
mov di, bx
|
||
|
add bx, cx
|
||
|
mov byte [bx], 0
|
||
|
.scan_loop:
|
||
|
cmp byte [di], 0
|
||
|
mov si, notfound_string
|
||
|
jz find_error_si
|
||
|
mov si, kernel_mnt_name
|
||
|
call fat_compare_name
|
||
|
jz .found
|
||
|
and di, not 1Fh
|
||
|
add di, 20h
|
||
|
jmp .scan_loop
|
||
|
.found:
|
||
|
and di, not 1Fh
|
||
|
mov si, directory_string
|
||
|
test byte [di+0Bh], 10h
|
||
|
jnz find_error_si
|
||
|
; found, now load it to 1000h:0000h
|
||
|
mov ax, [di+1Ah]
|
||
|
; first cluster of kernel.mnt in ax
|
||
|
; translate it to sector on disk in kolibri.img
|
||
|
push ax
|
||
|
dec ax
|
||
|
dec ax
|
||
|
movzx cx, byte [50Dh]
|
||
|
mul cx
|
||
|
add ax, [img_data_start]
|
||
|
; now ax is sector in kolibri.img
|
||
|
mov [kernel_mnt_in_img], ax
|
||
|
div [sect_per_clust]
|
||
|
; now ax is cluster in kolibri.img and
|
||
|
; dx is offset from the beginning of cluster
|
||
|
movzx eax, ax
|
||
|
push 2000h
|
||
|
pop ds
|
||
|
mov si, 1
|
||
|
.scani:
|
||
|
sub eax, [si]
|
||
|
jb .scanidone
|
||
|
; sanity check
|
||
|
cmp dword [si], 0
|
||
|
push invalid_read_request_string
|
||
|
jz find_error_sp
|
||
|
pop cx
|
||
|
; next chunk
|
||
|
add si, 8
|
||
|
jmp .scani
|
||
|
.scanidone:
|
||
|
add eax, [si] ; undo last subtract
|
||
|
add eax, [si+4] ; get cluster
|
||
|
push 0
|
||
|
pop ds
|
||
|
movzx ecx, [sect_per_clust]
|
||
|
push dx
|
||
|
mul ecx ; get sector
|
||
|
pop dx
|
||
|
movzx edx, dx
|
||
|
add eax, edx
|
||
|
add eax, [data_start]
|
||
|
mov [kernel_mnt_1st], eax
|
||
|
pop ax
|
||
|
push 1000h
|
||
|
pop es
|
||
|
.read_loop:
|
||
|
push ax
|
||
|
xor bx, bx
|
||
|
call img_read_cluster
|
||
|
shl cx, 9-4
|
||
|
mov ax, es
|
||
|
add ax, cx
|
||
|
mov es, ax
|
||
|
pop ax
|
||
|
call img_next_cluster
|
||
|
jc .read_loop
|
||
|
mov ax, 'KL'
|
||
|
mov si, loader_block
|
||
|
jmp 1000h:0000h
|
||
|
|
||
|
img_next_cluster:
|
||
|
mov bx, 700h
|
||
|
push ax
|
||
|
shr ax, 1
|
||
|
add ax, [esp]
|
||
|
mov dx, ax
|
||
|
shr ax, 9
|
||
|
add ax, word [fat_start]
|
||
|
mov cx, 2
|
||
|
push es
|
||
|
push ds
|
||
|
pop es
|
||
|
call read_img
|
||
|
pop es
|
||
|
and dx, 1FFh
|
||
|
add bx, dx
|
||
|
mov ax, [bx]
|
||
|
pop cx
|
||
|
test cx, 1
|
||
|
jz .1
|
||
|
shr ax, 4
|
||
|
.1:
|
||
|
and ax, 0FFFh
|
||
|
mov si, bad_cluster_string
|
||
|
cmp ax, 0FF7h
|
||
|
jz find_error_si
|
||
|
ret
|
||
|
img_read_cluster:
|
||
|
dec ax
|
||
|
dec ax
|
||
|
movzx cx, byte [50Dh] ; sects_per_clust
|
||
|
mul cx
|
||
|
add ax, [img_data_start]
|
||
|
movzx eax, ax
|
||
|
; call read_img
|
||
|
; ret
|
||
|
read_img:
|
||
|
; in: ax = sector, es:bx->buffer, cx=length in sectors
|
||
|
pushad
|
||
|
movzx ebx, bx
|
||
|
mov si, movedesc
|
||
|
shl eax, 9
|
||
|
add eax, 93100000h
|
||
|
mov dword [si+sou_addr-movedesc], eax
|
||
|
mov eax, 9300000h
|
||
|
mov ax, es
|
||
|
shl eax, 4
|
||
|
add eax, ebx
|
||
|
mov [si+dest_addr-movedesc], eax
|
||
|
mov ah, 87h
|
||
|
shl cx, 8 ; mul 200h/2
|
||
|
push es
|
||
|
push 0
|
||
|
pop es
|
||
|
int 15h
|
||
|
pop es
|
||
|
cmp ah, 0
|
||
|
mov si, exmem_string
|
||
|
jnz find_error_si
|
||
|
popad
|
||
|
ret
|
||
|
|
||
|
movedesc:
|
||
|
times 16 db 0
|
||
|
; source
|
||
|
dw 0xFFFF ; segment length
|
||
|
sou_addr dw 0000h ; linear address
|
||
|
db 1 ; linear address
|
||
|
db 93h ; access rights
|
||
|
dw 0
|
||
|
; destination
|
||
|
dw 0xFFFF ; segment length
|
||
|
dest_addr dd 93100000h ; high byte contains access rights
|
||
|
; three low bytes contains linear address (updated when reading)
|
||
|
dw 0
|
||
|
times 32 db 0
|
||
|
|
||
|
find_error_si:
|
||
|
push si
|
||
|
find_error_sp:
|
||
|
mov si, error_msg
|
||
|
call out_string
|
||
|
mov si, [cur_obj]
|
||
|
call out_string
|
||
|
mov si, colon
|
||
|
call out_string
|
||
|
pop si
|
||
|
call out_string
|
||
|
mov si, newline
|
||
|
call out_string
|
||
|
or [fat_cur_sector], -1
|
||
|
mov [imgnameofs], kolibri_img_name
|
||
|
call restore_slash
|
||
|
mov sp, 0xFFFE
|
||
|
jmp next_partition
|
||
|
|
||
|
file_not_found:
|
||
|
mov si, [esp+2]
|
||
|
mov [cur_obj], si
|
||
|
push notfound_string
|
||
|
jmp find_error_sp
|
||
|
|
||
|
restore_slash:
|
||
|
mov si, [missing_slash]
|
||
|
test si, si
|
||
|
jz @f
|
||
|
and [missing_slash], 0
|
||
|
mov byte [si], '\'
|
||
|
@@: ret
|
||
|
|
||
|
include 'fat32.inc'
|
||
|
include 'ntfs.inc'
|
||
|
|
||
|
write1st:
|
||
|
; callback from kernel.mnt
|
||
|
; write first sector of kernel.mnt from 1000:0000 back to disk
|
||
|
push cs
|
||
|
pop ds
|
||
|
push cs
|
||
|
pop es
|
||
|
; sanity check
|
||
|
mov bx, 500h
|
||
|
mov si, bx
|
||
|
mov cx, 1
|
||
|
push cx
|
||
|
mov eax, [kernel_mnt_1st]
|
||
|
push eax
|
||
|
call relative_read
|
||
|
push 1000h
|
||
|
pop es
|
||
|
xor di, di
|
||
|
mov cx, 8
|
||
|
repz cmpsw
|
||
|
mov si, data_error_msg
|
||
|
jnz find_error_si
|
||
|
; ok, now write back to disk
|
||
|
or byte [read.patch1+2], 1
|
||
|
or byte [read.patch2+2], 1
|
||
|
xor bx, bx
|
||
|
pop eax
|
||
|
pop cx
|
||
|
call relative_read
|
||
|
and byte [read.patch1+1], not 1
|
||
|
and byte [read.patch2+2], not 2
|
||
|
; and to image in memory (probably this may be done by kernel.mnt itself?)
|
||
|
mov dword [sou_addr], 93010000h
|
||
|
movzx eax, [kernel_mnt_in_img]
|
||
|
shl eax, 9
|
||
|
add eax, 93100000h
|
||
|
mov dword [dest_addr], eax
|
||
|
mov si, movedesc
|
||
|
push ds
|
||
|
pop es
|
||
|
mov ah, 87h
|
||
|
mov cx, 100h
|
||
|
int 15h
|
||
|
cmp ah, 0
|
||
|
mov si, exmem_string
|
||
|
jnz find_error_si
|
||
|
retf
|
||
|
|
||
|
loader_block:
|
||
|
db 1 ; version
|
||
|
dw 1 ; flags - image is loaded
|
||
|
dw write1st ; offset
|
||
|
dw 0 ; segment
|
||
|
|
||
|
fat_cur_sector dd -1
|
||
|
imgnameofs dw kolibri_img_name
|
||
|
|
||
|
; -----------------------------------------------
|
||
|
; ------------------ Settings -------------------
|
||
|
; -----------------------------------------------
|
||
|
|
||
|
; must be in lowercase, see ntfs_parse_dir.scan, fat32_parse_dir.scan
|
||
|
kernel_mnt_name db 'kernel.mnt',0
|
||
|
kolibri_img_name db 'kolibri.img',0
|
||
|
|
||
|
; change next variable if you want to boot from other physical drive
|
||
|
boot_drive db 80h
|
||
|
|
||
|
total_kaput db 13,10,'Fatal: image is not found.',13,10,0
|
||
|
missing_slash dw 0
|
||
|
align 2
|
||
|
|
||
|
cur_partition_ofs dw 0xF1BE
|
||
|
extended_part_start dd 0
|
||
|
extended_part_cur dd 0
|
||
|
extended_parent dd 0
|
||
|
|
||
|
; uninitialized data follows
|
||
|
drive_size dd ? ; in sectors
|
||
|
heads dw ?
|
||
|
sectors dw ?
|
||
|
cyls dw ?
|
||
|
partition_start dd ?
|
||
|
free dw ?
|
||
|
cur_obj dw ?
|
||
|
data_start dd ?
|
||
|
img_data_start dw ?
|
||
|
sect_per_clust dw ?
|
||
|
kernel_mnt_in_img dw ?
|
||
|
kernel_mnt_1st dd ?
|
||
|
; NTFS data
|
||
|
cluster_size dd ? ; in bytes
|
||
|
frs_size dd ? ; in bytes
|
||
|
frs_sectors dw ? ; in sectors
|
||
|
mft_data_attr dw ?
|
||
|
index_root dw ?
|
||
|
index_alloc dw ?
|
||
|
ofs dw ?
|
||
|
dir dw ?
|
||
|
; FAT32 data
|
||
|
fat_start dd ?
|
||
|
cur_cluster dd ?
|
||
|
; file must be 16 sectors long
|
||
|
|
||
|
repeat 0F000h - $
|
||
|
db 2
|
||
|
end repeat
|