; KolibriOS bootloader ; this code has been written by diamond in 2005,2006,2007 specially for KolibriOS ; this code is loaded by our bootsector to 0000:8000 format binary use16 out_string = 0x7DA2 read_cluster = 0x7D0A relative_read = 0x7D18 next_cluster = 0x7D5C org 0x8000 start: ; cs=ds=0, es undefined, ss=0, sp=7C00 movzx esp, sp push 1000h pop es ; say hi to user mov si, start_msg call out_string ; parse image name mov eax, [7C2Ch] ; root_cluster and eax, 0xFFFFFFF 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 [es:di+0Bh], 10h mov si, notdir_string jz find_error_si jmp .parsedir .end: test byte [es:di+0Bh], 10h mov si, directory_string jnz find_error_si ; parse FAT chunk ; runlist at 5000:0000 mov di, 4 push 5000h pop es mov dword [es:di-4], 1 stosd .parsefat: call next_cluster 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 read_img_file: xor si, si push es pop fs ; yes! Now read file to 0x100000 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 esi, byte [7C0Dh] mul esi add eax, [7A04h] push ax mov ax, 0x200 div si cmp cx, ax jb @f mov cx, ax @@: pop ax add [esp+1Ch], ecx sub [esp+18h], cx imul cx, si push cx call relative_read pop cx ; move it to extended memory mov byte [sou_addr+2], 1 .move_loop: push cx cmp cx, 80h jbe @f mov cx, 80h @@: mov ah, 87h xchg cl, ch mov si, movedesc push cx es push ds pop es int 15h pop es cx test ah, ah mov si, exmem_string jnz find_error_si add [dest_addr], ecx add [dest_addr], ecx inc byte [sou_addr+2] mov al, ch mov ah, cl pop cx sub cx, ax jnz .move_loop popad test cx, cx jnz .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 movzx cx, byte [7C0Dh] div cx ; now ax is cluster in kolibri.img and ; dx is offset from the beginning of cluster movzx eax, ax push 5000h pop ds xor si, si mov si, 1 .scani: sub eax, [si] jb .scanidone ; sanity check cmp dword [si], 0 push data_error_msg 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, byte [7C0Dh] push dx mul ecx ; get sector pop dx movzx edx, dx add eax, edx add eax, [7A04h] 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 jmp $ 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' if 0 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 else write1st = 0 end if loader_block: db 1 ; version dw 1 ; flags - image is loaded dw write1st ; offset dw 0 ; segment 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 missing_slash dw 0 start_msg db 2,' KolibriOS bootloader, FAT32 flash version' newline db 13,10,0 error_msg db 'Error' colon db ': ',0 root_string db '\',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 exmem_string db 'extended memory error',0 bad_cluster_string db 'bad cluster',0 data_error_msg db 'data error',0 align 2 ; uninitialized data follows cur_obj dw ? img_data_start dw ? kernel_mnt_in_img dw ? fat_start dw ? kernel_mnt_1st dd ?