; Copyright (c) 2008-2009, diamond ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions are met: ; * Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; * Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in the ; documentation and/or other materials provided with the distribution. ; * Neither the name of the nor the ; names of its contributors may be used to endorse or promote products ; derived from this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''AS IS'' AND ANY ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ; DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;***************************************************************************** use_lba = 1 org 0x7C00 jmp start nop ; FAT parameters, BPB ; they must be changed at install, replaced with real values rb 8 ; BS_OEMName, ignored dw 200h ; BPB_BytsPerSec BPB_SecsPerClus db ? BPB_RsvdSecCnt dw ? BPB_NumFATs db ? BPB_RootEntCnt dw ? dw ? ; BPB_TotSec16 db ? ; BPB_Media dw ? ; BPB_FATSz16 = 0 for FAT32 BPB_SecPerTrk dw ? BPB_NumHeads dw ? BPB_HiddSec dd ? dd ? ; BPB_TotSec32 BPB_FATSz32 dd ? BPB_ExtFlags dw ? dw ? ; BPB_FSVer BPB_RootClus dd ? dw ? ; BPB_FSInfo BPB_BkBootSec dw ? rb 12 ; BPB_Reserved BS_DrvNum db ? db ? ; BS_Reserved1 db ? ; BS_BootSig dd ? ; BS_VolID rb 11 ; BS_VolLab rb 8 ; curseg dw 0x8000 start: xor ax, ax mov ss, ax mov sp, 0x7C00 mov ds, ax mov bp, sp cld sti push dx ; byte [bp-2] = boot drive if use_lba mov ah, 41h mov bx, 55AAh int 13h mov si, aNoLBA jc err_ cmp bx, 0AA55h jnz err_ test cl, 1 jz err_ else mov ah, 8 int 13h jc @f movzx ax, dh inc ax mov [bp+BPB_NumHeads-0x7C00], ax and cx, 3Fh mov [bp+BPB_SecPerTrk-0x7C00], cx @@: end if ; get FAT parameters xor bx, bx movzx eax, [bp+BPB_NumFATs-0x7C00] mul [bp+BPB_FATSz32-0x7C00] movzx ecx, [bp+BPB_RsvdSecCnt-0x7C00] push ecx ; FAT start = dword [bp-6] add eax, ecx push eax ; data start = dword [bp-10] ;push dword -1 ; dword [bp-14] = current sector for FAT cache db 66h push -1 ; dword [bp-14] = current sector for FAT cache mov eax, [bp+BPB_RootClus-0x7C00] mov si, main_loader call lookup_in_dir jnc kordldr_ok noloader: mov si, aLoaderNotFound err_: call out_string mov si, aPressAnyKey call out_string xor ax, ax int 16h int 18h jmp $ kordldr_ok: mov eax, [es:di+20-2] ; hiword(eax) = hiword(cluster) mov ax, [es:di+26] ; loword(eax) = loword(cluster) mov es, bx ; es = 0 mov bx, 0x7E00 push bx ; save return address: bx = 7E00 ; fall through - 'ret' in read_cluster will return to 7E00 read_cluster: ; ss:bp = 0:7C00 ; es:bx = pointer to data ; eax = cluster sub eax, 2 movzx ecx, [bp+BPB_SecsPerClus-0x7C00] mul ecx read_sectors2: ; same as read_sectors32, but eax is relative to start of data add eax, [bp-10] read_sectors32: ; ss:bp = 0:7C00 ; es:bx = pointer to data ; eax = first sector ; cx = number of sectors ; some high words of 32-bit registers are destroyed! pusha add eax, [bp+BPB_HiddSec-0x7C00] if use_lba push ds do_read_sectors: push ax push cx cmp cx, 0x7F jbe @f mov cx, 0x7F @@: ; create disk address packet on the stack ; dq starting LBA push 0 push 0 push eax ; dd buffer push es push bx ; dw number of blocks to transfer (no more than 0x7F) push cx ; dw packet size in bytes push 10h ; issue BIOS call push ss pop ds mov si, sp mov dl, [bp-2] mov ah, 42h int 13h mov si, aReadError jc err_ ; restore stack add sp, 10h ; increase current sector & buffer; decrease number of sectors movzx esi, cx mov ax, es shl cx, 5 add ax, cx mov es, ax pop cx pop ax add eax, esi sub cx, si jnz do_read_sectors pop ds popa ret else do_read_sectors: pusha pop edi ; loword(edi) = di, hiword(edi) = si push bx ; eax / (SectorsPerTrack) -> eax, remainder bx movzx esi, [bp+BPB_SecPerTrk-0x7C00] xor edx, edx div esi mov bx, dx ; bx=sector-1 ; eax -> dx:ax push eax pop ax pop dx ; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx div [bp+BPB_NumHeads-0x7C00] ; number of sectors: read no more than to end of track sub si, bx cmp cx, si jbe @f mov cx, si @@: inc bx ; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format movzx edi, cx mov dh, dl mov dl, [bp-2] shl ah, 6 mov ch, al mov al, cl mov cl, bl or cl, ah pop bx mov si, 3 mov ah, 2 @@: push ax int 13h jnc @f xor ax, ax int 13h ; reset drive pop ax dec si jnz @b mov si, aReadError jmp err_ @@: pop ax mov ax, es mov cx, di shl cx, 5 add ax, cx mov es, ax push edi popa add eax, edi sub cx, di jnz do_read_sectors popa ret end if lookup_in_dir: ; in: ds:si -> 11-bytes FAT name ; in: eax = cluster ; in: bx = 0 ; out: if found: CF=0, es:di -> directory entry ; out: if not found: CF=1 ; push 0x8000 ; pop es ; read current cluster: first cluster goes to 8000:0000, others - to 8200:0000 mov es, [bp-7C00h + curseg] push es push eax call read_cluster mov ax, es cmp ah, 82h jb @f mov ax, 8200h @@: mov [bp-7C00h + curseg], ax pop eax pop es ; scan for filename shl cx, 4 xor di, di sloop: cmp byte [es:di], bl jz snotfound test byte [es:di+11], 8 ; volume label? jnz scont ; ignore volume labels pusha mov cx, 11 repz cmpsb popa jz sdone scont: add di, 0x20 loop sloop ; next cluster push 0x6000 pop es push es ax shr eax, 7 cmp eax, [bp-14] mov [bp-14], eax jz @f add eax, [bp-6] mov cx, 1 call read_sectors32 @@: pop di es and di, 0x7F shl di, 2 and byte [es:di+3], 0x0F mov eax, [es:di] ;and eax, 0x0FFFFFFF cmp eax, 0x0FFFFFF7 jb lookup_in_dir snotfound: stc sdone: ret out_string: ; in: ds:si -> ASCIIZ string lodsb test al, al jz sdone mov ah, 0Eh mov bx, 7 int 10h jmp out_string aReadError db 'Read error',0 if use_lba aNoLBA db 'The drive does not support LBA!',0 end if aLoaderNotFound db 'Loader not found',0 aPressAnyKey db 13,10,'Press any key...',13,10,0 main_loader db 'KORDLDR F32' db 56h ; just to make file 512 bytes long :) db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' ; bootsector signature dw 0xAA55 ; display offsets of all procedures used by kordldr.f12.asm macro show [procedure] { bits = 16 display `procedure,' = ' repeat bits/4 d = '0' + procedure shr (bits - %*4) and 0Fh if d > '9' d = d + 'A'-'9'-1 end if display d end repeat display 13,10 } show read_sectors32, read_sectors2, err_, noloader