Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 1064 → Rev 1065

/kernel/trunk/sec_loader/trunk/boot/fat1x/bootsect.asm
0,0 → 1,392
; 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 <organization> 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 <Lrz> ''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 <copyright holder> 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 = 0
org 0x7C00
jmp start
nop
; FAT parameters, BPB
; note: they can be changed at install, replaced with real values
; these settings are for most typical 1.44M floppies
db 'KOLIBRI ' ; BS_OEMName, ignored
dw 200h ; BPB_BytsPerSec
BPB_SecsPerClus db 1
BPB_RsvdSecCnt dw 1
BPB_NumFATs db 2
BPB_RootEntCnt dw 0xE0
dw 2880 ; BPB_TotSec16
db 0xF0 ; BPB_Media
BPB_FATSz16 dw 9
BPB_SecPerTrk dw 18
BPB_NumHeads dw 2
BPB_HiddSec dd 0
dd 0 ; BPB_TotSec32
BS_DrvNum db 0
db 0 ; BS_Reserved1
db ')' ; BS_BootSig
dd 12344321h ; BS_VolID
filename:
db 'KORD.OS ' ; BS_VolLab
db 'FAT12 ' ; BS_FilSysType
; Used memory map:
; 8000:0000 - current directory
; 9000:0000 - root directory data [cached]
start:
xor ax, ax
mov ss, ax
mov sp, 0x7C00
mov ds, ax
mov bp, sp
cld
sti
mov [bp+BS_DrvNum-0x7C00], dl
if use_lba
mov ah, 41h
mov bx, 55AAh
int 13h
mov si, aNoLBA
jc err
cmp bx, 0AA55h
jnz err
test cx, 1
jz err
else
mov ah, 8
int 13h
jc @f ; on error, assume that BPB geometry is valid
mov al, dh
mov ah, 0
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
mov al, [bp+BPB_NumFATs-0x7C00]
mov ah, 0
mul [bp+BPB_FATSz16-0x7C00]
add ax, [bp+BPB_RsvdSecCnt-0x7C00]
adc dx, bx
push dx
push ax ; root directory start = dword [bp-4]
mov cx, [bp+BPB_RootEntCnt-0x7C00]
add cx, 0xF
rcr cx, 1
shr cx, 3 ; cx = size of root directory in sectors
add ax, cx
adc dx, bx
push dx
push ax ; data start = dword [bp-8]
; load start of root directory (no more than 0x2000 bytes = 0x10 sectors)
cmp cx, 0x10
jb @f
mov cx, 0x10
@@:
mov ax, [bp-4]
mov dx, [bp-2]
push 0x9000
pop es
call read_sectors
add word [bp-4], cx ; dword [bp-4] = start of non-cached root data
adc word [bp-2], bx
; load kordldr.f12
mov si, main_loader
call lookup_in_root_dir
jc noloader
test byte [es:di+11], 10h ; directory?
jz 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 ax, [es:di+26] ; get file cluster
mov bx, 0x7E00
xor cx, cx
mov es, cx
sub ax, 2
jc noloader
push bx ; save return address: bx = 7E00
mov cl, [bp+BPB_SecsPerClus-0x7C00]
mul cx
; fall through - 'ret' in read_sectors will return to 7E00
 
read_sectors2:
; same as read_sectors, but dx:ax is relative to start of data
add ax, [bp-8]
adc dx, [bp-6]
read_sectors:
; ss:bp = 0:7C00
; es:bx = pointer to data
; dx:ax = first sector
; cx = number of sectors
pusha
add ax, word [bp+BPB_HiddSec-0x7C00]
adc dx, word [bp+BPB_HiddSec+2-0x7C00]
if use_lba
push ds
do_read_sectors:
push ax
push cx
push dx
cmp cx, 0x7F
jbe @f
mov cx, 0x7F
@@:
; create disk address packet on the stack
; dq starting LBA
push 0
push 0
push dx
push ax
; 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+BS_DrvNum-0x7C00]
mov ah, 42h
int 13h
mov si, aReadError
jc err
; restore stack
add sp, 10h
; increase current sector & buffer; decrease number of sectors
mov si, cx
mov ax, es
shl cx, 5
add ax, cx
mov es, ax
pop dx
pop cx
pop ax
add ax, si
adc dx, 0
sub cx, si
jnz do_read_sectors
pop ds
popa
ret
else
do_read_sectors:
pusha
pop di
push bx
 
; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx
mov si, ax
xchg ax, dx
xor dx, dx
div [bp+BPB_SecPerTrk-0x7C00]
push ax
mov ax, si
div [bp+BPB_SecPerTrk-0x7C00]
mov bx, dx ; bx=sector-1
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
push bx
sub bx, [bp+BPB_SecPerTrk-0x7C00]
neg bx
cmp cx, bx
jbe @f
mov cx, bx
@@:
pop bx
 
inc bx
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format
mov di, cx
mov dh, dl
mov dl, [bp+BS_DrvNum-0x7C00]
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 di
popa
add ax, di
adc dx, 0
sub cx, di
jnz do_read_sectors
popa
ret
end if
 
scan_for_filename:
; in: ds:si -> 11-bytes FAT name
; in: es:0 -> part of directory data
; in: cx = number of entries
; out: if found: CF=0, ZF=1, es:di -> directory entry
; out: if not found, but continue required: CF=1 and ZF=0
; out: if not found and zero item reached: CF=1 and ZF=1
xor di, di
push cx
sloop:
cmp byte [es:di], 0
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
inc cx ; clear ZF flag
snotfound:
stc
sdone:
pop cx
lrdret:
ret
 
lookup_in_root_dir:
; ss:bp = 0:7C00
; in: ds:si -> 11-bytes FAT name
; out: if found: CF=0, es:di -> directory entry
; out: if not found: CF=1
mov cx, [bp+BPB_RootEntCnt-0x7C00]
push cx
; first, look in root directory cache
push 0x9000
pop es
test ch, ch
jz @f
mov cx, 0x100
@@:
mov ax, [bp-4]
mov dx, [bp-2] ; dx:ax = starting sector of not cached data of root directory
lrdloop:
call scan_for_filename
pop bx
jz lrdret
sub bx, cx
mov cx, bx
stc
jz lrdret
; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries
push cx
cmp ch, 0x8
jb @f
mov cx, 0x800
@@:
push 0x8000
pop es
push cx
push es
xor bx, bx
add cx, 0xF
shr cx, 4
call read_sectors
pop es
add ax, cx
adc dx, bx
pop cx
jmp lrdloop
 
out_string:
; in: ds:si -> ASCIIZ string
lodsb
test al, al
jz lrdret
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 F1X'
 
if use_lba
db 0 ; make bootsector 512 bytes in length
end if
 
; 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_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err, noloader
/kernel/trunk/sec_loader/trunk/boot/fat1x/bootsect.txt
0,0 → 1,360
; 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 <organization> 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 <Lrz> ''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 <copyright holder> 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.
;*****************************************************************************
 
Âñòðå÷àþòñÿ âèðóñ è FAT.
- Ïðèâåò, òû êòî?
- ß? Âèðóñ.
- A ÿ AFT, òî åñòü TAF, òî åñòü FTA, ÷åðò, ñîâñåì çàïóòàëñÿ...
 
Áóòñåêòîð äëÿ FAT12/FAT16-òîìà íà íîñèòåëå ñ ðàçìåðîì ñåêòîðà 0x200 = 512 áàéò.
 
=====================================================================
 
Åñòü äâå âåðñèè â çàâèñèìîñòè îò òîãî, ïîääåðæèâàåò ëè íîñèòåëü LBA,
âûáîð îñóùåñòâëÿåòñÿ óñòàíîâêîé êîíñòàíòû use_lba â ïåðâîé ñòðîêå èñõîäíèêà.
Òðåáîâàíèÿ äëÿ ðàáîòû:
1) Ñàì áóòñåêòîð, ïåðâàÿ êîïèÿ FAT è âñå èñïîëüçóåìûå ôàéëû
äîëæíû áûòü ÷èòàáåëüíû.
2) Ìèíèìàëüíûé ïðîöåññîð - 80186.
3) Â ñèñòåìå äîëæíî áûòü êàê ìèíèìóì 592K ñâîáîäíîé áàçîâîé ïàìÿòè.
 
=====================================================================
 
Äîêóìåíòàöèÿ â òåìó (ññûëêè âàëèäíû íà ìîìåíò íàïèñàíèÿ ýòîãî ôàéëà, 15.05.2008):
îôèöèàëüíàÿ ñïåöèôèêàöèÿ FAT: http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
â ôîðìàòå PDF: http://staff.washington.edu/dittrich/misc/fatgen103.pdf
ðóññêèé ïåðåâîä: http://wasm.ru/docs/11/fatgen103-rus.zip
îôèöèàëüíàÿ ñïåöèôèêàöèÿ ðàñøèðåíèÿ EDD BIOS 3.0: http://www.phoenix.com/NR/rdonlyres/19FEBD17-DB40-413C-A0B1-1F3F560E222F/0/specsedd30.pdf
òî æå, âåðñèÿ 1.1: http://www.phoenix.com/NR/rdonlyres/9BEDED98-6B3F-4DAC-BBB7-FA89FA5C30F0/0/specsedd11.pdf
îïèñàíèå ôóíêöèé BIOS: Interrupt List by Ralf Brown: http://www.cs.cmu.edu/~ralf/files.html
îôèöèàëüíàÿ ñïåöèôèêàöèÿ Boot BIOS: http://www.phoenix.com/NR/rdonlyres/56E38DE2-3E6F-4743-835F-B4A53726ABED/0/specsbbs101.pdf
 
=====================================================================
 
Ìàêñèìàëüíîå êîëè÷åñòâî êëàñòåðîâ íà FAT12-òîìå - 0xFF4 = 4084; êàæäûé êëàñòåð
çàíèìàåò 12 áèò â òàáëèöå FAT, òàê ÷òî îáùèé ðàçìåð íå ïðåâîñõîäèò
0x17EE = 6126 áàéò. Âñÿ òàáëèöà ïîìåùàåòñÿ â ïàìÿòè.
Ìàêñèìàëüíîå êîëè÷åñòâî êëàñòåðîâ íà FAT16-òîìå - 0xFFF4 = 65524; êàæäûé
êëàñòåð çàíèìàåò 16 áèò â òàáëèöå FAT, òàê ÷òî îáùèé ðàçìåð íå ïðåâîñõîäèò
0x1FFE8 = 131048 áàéò. Âñÿ òàáëèöà òàêæå ïîìåùàåòñÿ â ïàìÿòè, îäíàêî â
ýòîì ñëó÷àå íåñêîëüêî íåöåëåñîîáðàçíî ñ÷èòûâàòü âñþ òàáëèöó, ïîñêîëüêó
íà ïðàêòèêå íóæíà òîëüêî íåáîëüøàÿ å¸ ÷àñòü. Ïîýòîìó ìåñòî â ïàìÿòè
ðåçåðâèðóåòñÿ, íî äàííûå ñ÷èòûâàþòñÿ òîëüêî â ìîìåíò, êîãäà ê íèì
äåéñòâèòåëüíî èä¸ò îáðàùåíèå.
 
Ñõåìà èñïîëüçóåìîé ïàìÿòè:
...-7C00 ñòåê
7C00-7E00 êîä áóòñåêòîðà
7E00-8200 âñïîìîãàòåëüíûé ôàéë çàãðóç÷èêà (kordldr.f1x)
8200-8300 ñïèñîê çàãðóæåííûõ ñåêòîðîâ òàáëèöû FAT16
(1 = ñîîòâåòñòâóþùèé ñåêòîð çàãðóæåí)
60000-80000 çàãðóæåííàÿ òàáëèöà FAT12 / ìåñòî äëÿ òàáëèöû FAT16
80000-90000 òåêóùèé êëàñòåð òåêóùåé ðàññìàòðèâàåìîé ïàïêè
90000-92000 êýø äëÿ êîðíåâîé ïàïêè
92000-... êýø äëÿ íåêîðíåâûõ ïàïîê (êàæäîé ïàïêå îòâîäèòñÿ
2000h áàéò = 100h âõîäîâ, îäíîâðåìåííî â êýøå
ìîæåò íàõîäèòüñÿ íå áîëåå 7 ïàïîê;
òî÷íûé ðàçìåð îïðåäåëÿåòñÿ ðàçìåðîì äîñòóïíîé
ôèçè÷åñêîé ïàìÿòè - êàê ïðàâèëî, íåïîñðåäñòâåííî
ïåðåä A0000 ðàçìåùàåòñÿ EBDA, Extended BIOS Data Area)
 
=====================================================================
 
Îñíîâíîé ïðîöåññ çàãðóçêè.
Òî÷êà âõîäà (start): ïîëó÷àåò óïðàâëåíèå îò BIOS ïðè çàãðóçêå, ïðè ýòîì
dl ñîäåðæèò èäåíòèôèêàòîð äèñêà, ñ êîòîðîãî èä¸ò çàãðóçêà
1. Íàñòðàèâàåò ñòåê ss:sp = 0:7C00 (ñòåê ðàñïîëàãàåòñÿ íåïîñðåäñòâåííî ïåðåä
êîäîì), ñåãìåíò äàííûõ ds = 0, è óñòàíàâëèâàåò ss:bp íà íà÷àëî
áóòñåêòîðà (â äàëüíåéøåì äàííûå áóäóò àäðåñîâàòüñÿ ÷åðåç [bp+N] -
ýòî îñâîáîæäàåò ds è ýêîíîìèò íà ðàçìåðå êîäà).
2. LBA-âåðñèÿ: ïðîâåðÿåò, ïîääåðæèâàåò ëè íîñèòåëü LBA, âûçîâîì ôóíêöèè 41h
ïðåðûâàíèÿ 13h. Åñëè íåò, ïåðåõîäèò íà êîä îáðàáîòêè îøèáîê ñ
ñîîáùåíèåì îá îòñóòñòâèè LBA.
CHS-âåðñèÿ: îïðåäåëÿåò ãåîìåòðèþ íîñèòåëÿ âûçîâîì ôóíêöèè 8 ïðåðûâàíèÿ 13h è
çàïèñûâàåò ïîëó÷åííûå äàííûå ïîâåðõ BPB. Åñëè âûçîâ çàâåðøèëñÿ îøèáêîé,
ïðåäïîëàãàåò óæå ñóùåñòâóþùèå äàííûå êîððåêòíûìè.
3. Âû÷èñëÿåò íåêîòîðûå ïàðàìåòðû FAT-òîìà: íà÷àëüíûé ñåêòîð êîðíåâîé ïàïêè
è íà÷àëüíûé ñåêòîð äàííûõ. Êëàä¸ò èõ â ñòåê; âïîñëåäñòâèè îíè
âñåãäà áóäóò ëåæàòü â ñòåêå è àäðåñîâàòüñÿ ÷åðåç bp.
4. Ñ÷èòûâàåò íà÷àëî êîðíåâîé ïàïêè ïî àäðåñó 9000:0000. ×èñëî ñ÷èòûâàåìûõ
ñåêòîðîâ - ìèíèìóì èç ðàçìåðà êîðíåâîé ïàïêè, óêàçàííîãî â BPB, è 16
(ðàçìåð êýøà äëÿ êîðíåâîé ïàïêè - 2000h áàéò = 16 ñåêòîðîâ).
5. Èùåò â êîðíåâîé ïàïêå ýëåìåíò kordldr.f1x. Åñëè íå íàõîäèò, èëè åñëè
îí îêàçûâàåòñÿ ïàïêîé, èëè åñëè ôàéë èìååò íóëåâóþ äëèíó -
ïåðåõîäèò íà êîä îáðàáîòêè îøèáîê ñ ñîîáùåíèåì î
íåíàéäåííîì çàãðóç÷èêå.
Çàìå÷àíèå: íà ýòîì ýòàïå çàãðóçêè èñêàòü ìîæíî òîëüêî â êîðíåâîé
ïàïêå è òîëüêî èìåíà, çàäàííûå â ôîðìàòå ôàéëîâîé ñèñòåìå FAT
(8+3 - 8 áàéò íà èìÿ, 3 áàéòà íà ðàñøèðåíèå, âñå áóêâû äîëæíû
áûòü çàãëàâíûìè, ïðè íåîáõîäèìîñòè èìÿ è ðàñøèðåíèå äîïîëíÿþòñÿ
ïðîáåëàìè, ðàçäåëÿþùåé òî÷êè íåò, çàâåðøàþùåãî íóëÿ íåò).
6. Çàãðóæàåò ïåðâûé êëàñòåð ôàéëà kordldr.f1x ïî àäðåñó 0:7E00 è ïåðåäà¸ò
åìó óïðàâëåíèå. Ïðè ýòîì â ðåãèñòðàõ dx:ax îêàçûâàåòñÿ àáñîëþòíûé
íîìåð ïåðâîãî ñåêòîðà kordldr.f1x, à â cx - ÷èñëî ñ÷èòàííûõ ñåêòîðîâ
(ðàâíîå ðàçìåðó êëàñòåðà).
 
Âñïîìîãàòåëüíûå ïðîöåäóðû áóòñåêòîðà.
Êîä îáðàáîòêè îøèáîê (err):
1. Âûâîäèò ñòðîêó ñ ñîîáùåíèåì îá îøèáêå.
2. Âûâîäèò ñòðîêó "Press any key...".
3. Æä¸ò íàæàòèÿ any key.
4. Âûçûâàåò int 18h, äàâàÿ øàíñ BIOSó ïîïûòàòüñÿ çàãðóçèòüñÿ îòêóäà-íèáóäü åù¸.
5. Äëÿ ïîäñòðàõîâêè çàöèêëèâàåòñÿ.
 
Ïðîöåäóðà ÷òåíèÿ ñåêòîðîâ (read_sectors è read_sectors2):
íà âõîäå äîëæíî áûòü óñòàíîâëåíî:
ss:bp = 0:7C00
es:bx = óêàçàòåëü íà íà÷àëî áóôåðà, êóäà áóäóò ïðî÷èòàíû äàííûå
dx:ax = ñòàðòîâûé ñåêòîð (îòíîñèòåëüíî íà÷àëà ëîãè÷åñêîãî äèñêà
äëÿ read_sectors, îòíîñèòåëüíî íà÷àëà äàííûõ äëÿ read_sectors2)
cx = ÷èñëî ñåêòîðîâ (äîëæíî áûòü áîëüøå íóëÿ)
íà âûõîäå: es:bx óêàçûâàåò íà êîíåö áóôåðà, â êîòîðûé áûëè ïðî÷èòàíû äàííûå
0. Åñëè âûçûâàåòñÿ read_sectors2, îíà ïåðåâîäèò óêàçàííûé åé íîìåð ñåêòîðà
â íîìåð îòíîñèòåëüíî íà÷àëà ëîãè÷åñêîãî äèñêà, ïðèáàâëÿÿ íîìåð ñåêòîðà
íà÷àëà äàííûõ, õðàíÿùèéñÿ â ñòåêå êàê [bp-8].
1. Ïåðåâîäèò ñòàðòîâûé ñåêòîð (îòñ÷èòûâàåìûé îò íà÷àëà òîìà) â ñåêòîð íà
óñòðîéñòâå, ïðèáàâëÿÿ çíà÷åíèå ñîîòâåòñòâóþùåãî ïîëÿ èç BPB.
2.  öèêëå (øàãè 3-6) ÷èòàåò ñåêòîðû, ñëåäèò çà òåì, ÷òîáû íà êàæäîé èòåðàöèè
CHS-âåðñèÿ: âñå ÷èòàåìûå ñåêòîðû áûëè íà îäíîé äîðîæêå.
LBA-âåðñèÿ: ÷èñëî ÷èòàåìûõ ñåêòîðîâ íå ïðåâîñõîäèëî 7Fh (òðåáîâàíèå
ñïåöèôèêàöèè EDD BIOS).
CHS-âåðñèÿ:
3. Ïåðåâîäèò àáñîëþòíûé íîìåð ñåêòîðà â CHS-ñèñòåìó: ñåêòîð ðàññ÷èòûâàåòñÿ êàê
åäèíèöà ïëþñ îñòàòîê îò äåëåíèÿ àáñîëþòíîãî íîìåðà íà ÷èñëî ñåêòîðîâ
íà äîðîæêå; äîðîæêà ðàññ÷èòûâàåòñÿ êàê îñòàòîê îò äåëåíèÿ ÷àñòíîãî,
ïîëó÷åííîãî íà ïðåäûäóùåì øàãå, íà ÷èñëî äîðîæåê, à öèëèíäð - êàê
÷àñòíîå îò ýòîãî æå äåëåíèÿ. Åñëè ÷èñëî ñåêòîðîâ äëÿ ÷òåíèÿ áîëüøå,
÷åì ÷èñëî ñåêòîðîâ äî êîíöà äîðîæêè, óìåíüøàåò ÷èñëî ñåêòîðîâ äëÿ
÷òåíèÿ.
4. Ôîðìèðóåò äàííûå äëÿ âûçîâà int 13h (ah=2 - ÷òåíèå, al=÷èñëî ñåêòîðîâ,
dh=ãîëîâêà, (ìëàäøèå 6 áèò cl)=ñåêòîð,
(ñòàðøèå 2 áèòà cl è âåñü ch)=äîðîæêà, dl=äèñê, es:bx->áóôåð).
5. Âûçûâàåò BIOS. Åñëè BIOS ðàïîðòóåò îá îøèáêå, âûïîëíÿåò ñáðîñ äèñêà
è ïîâòîðÿåò ïîïûòêó ÷òåíèÿ, âñåãî äåëàåòñÿ íå áîëåå òð¸õ ïîïûòîê
(íåñêîëüêî ïîïûòîê íóæíî â ñëó÷àå äèñêåòû äëÿ ãàðàíòèè òîãî, ÷òî
ìîòîð ðàñêðóòèëñÿ). Åñëè âñå òðè ðàçà ïðîèñõîäèò îøèáêà ÷òåíèÿ,
ïåðåõîäèò íà êîä îáðàáîòêè îøèáîê ñ ñîîáùåíèåì "Read error".
6.  ñîîòâåòñòâèè ñ ÷èñëîì ïðî÷èòàííûõ íà òåêóùåé èòåðàöèè ñåêòîðîâ
êîððåêòèðóåò òåêóùèé ñåêòîð, ÷èñëî îñòàâøèõñÿ ñåêòîðîâ è óêàçàòåëü íà
áóôåð (â ïàðå es:bx êîððåêòèðóåòñÿ es). Åñëè âñ¸ ïðî÷èòàíî, çàêàí÷èâàåò
ðàáîòó, èíà÷å âîçâðàùàåòñÿ íà øàã 3.
LBA-âåðñèÿ:
3. Åñëè ÷èñëî ñåêòîðîâ äëÿ ÷òåíèÿ áîëüøå 7Fh, óìåíüøàåò åãî (äëÿ òåêóùåé
èòåðàöèè) äî 7Fh.
4. Ôîðìèðóåò â ñòåêå ïàêåò äëÿ int 13h (êëàä¸ò âñå íóæíûå äàííûå êîìàíäàìè
push, ïðè÷¸ì â îáðàòíîì ïîðÿäêå: ñòåê - ñòðóêòóðà LIFO, è äàííûå â
ñòåêå õðàíÿòñÿ â îáðàòíîì ïîðÿäêå ïî îòíîøåíèþ ê òîìó, êàê èõ òóäà
êëàëè).
5. Âûçûâàåò BIOS. Åñëè BIOS ðàïîðòóåò îá îøèáêå, ïåðåõîäèò íà êîä îáðàáîòêè
îøèáîê ñ ñîîáùåíèåì "Read error". Î÷èùàåò ñòåê îò ïàêåòà,
ñôîðìèðîâàííîãî íà ïðåäûäóùåì øàãå.
6.  ñîîòâåòñòâèè ñ ÷èñëîì ïðî÷èòàííûõ íà òåêóùåé èòåðàöèè ñåêòîðîâ
êîððåêòèðóåò òåêóùèé ñåêòîð, ÷èñëî îñòàâøèõñÿ ñåêòîðîâ è óêàçàòåëü íà
áóôåð (â ïàðå es:bx êîððåêòèðóåòñÿ es). Åñëè âñ¸ ïðî÷èòàíî, çàêàí÷èâàåò
ðàáîòó, èíà÷å âîçâðàùàåòñÿ íà øàã 3.
 
Ïðîöåäóðà ïîèñêà ýëåìåíòà ïî èìåíè â óæå ïðî÷èòàííûõ äàííûõ ïàïêè
(scan_for_filename):
íà âõîäå äîëæíî áûòü óñòàíîâëåíî:
ds:si = óêàçàòåëü íà èìÿ ôàéëà â ôîðìàòå FAT (11 áàéò, 8 íà èìÿ,
3 íà ðàñøèðåíèå, âñå áóêâû çàãëàâíûå, åñëè èìÿ/ðàñøèðåíèå
êîðî÷å, îíî äîïîëíÿåòñÿ äî ìàêñèìóìà ïðîáåëàìè)
es = ñåãìåíò äàííûõ ïàïêè
cx = ÷èñëî ýëåìåíòîâ â ïðî÷èòàííûõ äàííûõ
íà âûõîäå: ZF îïðåäåëÿåò, íóæíî ëè ïðîäîëæàòü ðàçáîð äàííûõ ïàïêè
(ZF=1, åñëè ëèáî íàéäåí çàïðîøåííûé ýëåìåíò, ëèáî äîñòèãíóò
êîíåö ïàïêè); CF îïðåäåëÿåò, óäàëîñü ëè íàéòè ýëåìåíò ñ èñêîìûì èìåíåì
(CF=1, åñëè íå óäàëîñü); åñëè óäàëîñü, òî es:di óêàçûâàåò íà íåãî.
scan_for_filename ñ÷èòàåò, ÷òî äàííûå ïàïêè ðàçìåùàþòñÿ íà÷èíàÿ ñ es:0.
Ïåðâîé êîìàíäîé ïðîöåäóðà îáíóëÿåò di. Çàòåì ïðîñòî â öèêëå ïî ýëåìåíòàì ïàïêè
ïðîâåðÿåò èìåíà.
 
Ïðîöåäóðà ïîèñêà ýëåìåíòà â êîðíåâîé ïàïêå (lookup_in_root_dir):
íà âõîäå äîëæíî áûòü óñòàíîâëåíî:
ss:bp = 0:7C00
ds:si = óêàçàòåëü íà èìÿ ôàéëà â ôîðìàòå FAT (ñì. âûøå)
íà âûõîäå: ôëàã CF îïðåäåëÿåò, óäàëîñü ëè íàéòè ôàéë; åñëè óäàëîñü, òî
CF ñáðîøåí è es:di óêàçûâàåò íà ýëåìåíò ïàïêè
Íà÷èíàåò ñ ïðîñìîòðà êýøèðîâàííîé (íà÷àëüíîé) ÷àñòè êîðíåâîé ïàïêè.  öèêëå
ñêàíèðóåò ýëåìåíòû; åñëè ïî ðåçóëüòàòàì ñêàíèðîâàíèÿ îáíàðóæèâàåò,
÷òî íóæíî ÷èòàòü ïàïêó äàëüøå, òî ñ÷èòûâàåò íå áîëåå 0x10000 = 64K
áàéò (îãðàíè÷åíèå ââåäåíî ïî äâóì ïðè÷èíàì: âî-ïåðâûõ, ÷òîáû çàâåäîìî
íå âûëåçòè çà ïðåäåëû èñïîëüçóåìîé ïàìÿòè, âî-âòîðûõ, ñêàíèðîâàíèå
ïðåäïîëàãàåò, ÷òî âñå îáðàáàòûâàåìûå ýëåìåíòû ðàñïîëàãàþòñÿ â îäíîì
ñåãìåíòå) è ïðîäîëæàåò öèêë.
Ñêàíèðîâàíèå ïðåêðàùàåòñÿ â òð¸õ ñëó÷àÿõ: îáíàðóæåí èñêîìûé ýëåìåíò;
êîí÷èëèñü ýëåìåíòû â ïàïêå (ñóäÿ ïî ÷èñëó ýëåìåíòîâ, óêàçàííîìó â BPB);
î÷åðåäíîé ýëåìåíò ïàïêè ñèãíàëèçèðóåò î êîíöå (ïåðâûé áàéò íóëåâîé).
 
Ïðîöåäóðà âûâîäà íà ýêðàí ASCIIZ-ñòðîêè (out_string):
íà âõîäå: ds:si -> ñòðîêà
 öèêëå, ïîêà íå äîñòèãíóò çàâåðøàþùèé íîëü, âûçûâàåò ôóíêöèþ int 10h/ah=0Eh.
 
=====================================================================
 
Ðàáîòà âñïîìîãàòåëüíîãî çàãðóç÷èêà kordldr.f1x:
1. Îïðåäåëÿåò, áûë ëè îí çàãðóæåí CHS- èëè LBA-âåðñèåé áóòñåêòîðà.
 çàâèñèìîñòè îò ýòîãî óñòàíàâëèâàåò ñìåùåíèÿ èñïîëüçóåìûõ ïðîöåäóð
áóòñåêòîðà. Êðèòåðèé ïðîâåðêè: scan_for_filename äîëæíà íà÷èíàòüñÿ
ñ èíñòðóêöèè 'xor di,di' ñ êîäîì 31 FF (âîîáùå-òî ýòà èíñòðóêöèÿ ìîæåò
ñ ðàâíûì óñïåõîì àññåìáëèðîâàòüñÿ è êàê 33 FF, íî fasm ãåíåðèðóåò
èìåííî òàêóþ ôîðìó).
2. Óçíà¸ò ðàçìåð ñâîáîäíîé áàçîâîé ïàìÿòè (ò.å. ñâîáîäíîãî íåïðåðûâíîãî êóñêà
àäðåñîâ ïàìÿòè, íà÷èíàþùåãîñÿ ñ 0) âûçîâîì int 12h.  ñîîòâåòñòâèè ñ
íèì âû÷èñëÿåò ÷èñëî ýëåìåíòîâ â êýøå ïàïîê. Õîòÿ áû äëÿ îäíîãî ýëåìåíòà
ìåñòî äîëæíî áûòü, îòñþäà îãðàíè÷åíèå â 592 Kb (94000h áàéò).
Çàìå÷àíèå: ýòîò ðàçìåð íå ìîæåò ïðåâîñõîäèòü 0A0000h áàéò è
íà ïðàêòèêå îêàçûâàåòñÿ íåìíîãî (íà 1-2 êèëîáàéòà) ìåíüøèì èç-çà
íàëè÷èÿ äîïîëíèòåëüíîé îáëàñòè äàííûõ BIOS "ââåðõó" áàçîâîé ïàìÿòè.
3. Îïðåäåëÿåò òèï ôàéëîâîé ñèñòåìû: FAT12 èëè FAT16. Ñîãëàñíî îôèöèàëüíîé
ñïåöèôèêàöèè îò Microsoft (âåðñèÿ 1.03 ñïåöèôèêàöèè äàòèðîâàíà,
ê ñëîâó, 06 äåêàáðÿ 2000 ãîäà), ðàçðÿäíîñòü FAT îïðåäåëÿåòñÿ
èñêëþ÷èòåëüíî ÷èñëîì êëàñòåðîâ: ìàêñèìàëüíîå ÷èñëî êëàñòåðîâ íà
FAT12-òîìå ðàâíî 4094 = 0xFF4. Ñîãëàñíî çäðàâîìó ñìûñëó, íà FAT12
ìîæåò áûòü 0xFF5 êëàñòåðîâ, íî íå áîëüøå: êëàñòåðû íóìåðóþòñÿ ñ 2,
à ÷èñëî 0xFF7 íå ìîæåò áûòü êîððåêòíûì íîìåðîì êëàñòåðà.
Win95/98/Me ñëåäóåò çäðàâîìó ñìûñëó: ðàçãðàíè÷åíèå FAT12/16 äåëàåòñÿ
ïî ìàêñèìóìó 0xFF5. Äðàéâåð FAT â WinNT/2k/XP/Vista âîîáùå ïîñòóïàåò
ÿâíî íåâåðíî, ñ÷èòàÿ, ÷òî 0xFF6 (èëè ìåíüøå) êëàñòåðîâ îçíà÷àåò
FAT12-òîì, â ðåçóëüòàòå ïîëó÷àåòñÿ, ÷òî ïîñëåäíèé êëàñòåð
(â ñëó÷àå 0xFF6) íåàäðåñóåì. Îñíîâíîé çàãðóç÷èê osloader.exe
[âñòðîåí â ntldr] äëÿ NT/2k/XP äåëàåò òàê æå. Ïåðâè÷íûé çàãðóç÷èê
[áóòñåêòîð FAT12/16 çàãðóæàåò ïåðâûé ñåêòîð ntldr, è ðàçáîð FAT-òàáëèöû
ëåæèò íà í¸ì] â NT/2k ïîäâåðæåí òîé æå îøèáêå.  XP å¸ òàêè èñïðàâèëè
â ñîîòâåòñòâèè ñî ñïåöèôèêàöèåé. Linux ïðè îïðåäåëåíèè FAT12/FAT16
÷åñòíî ñëåäóåò ñïåöèôèêàöèè.
Çäåñü êîä îñíîâàí âñ¸ æå íà ñïåöèôèêàöèè. 9x ìåðòâà, à â ëèíåéêå NT
Microsoft åñëè è áóäåò èñïðàâëÿòü îøèáêè, òî ñîãëàñíî ñîáñòâåííîìó
îïèñàíèþ.
4. Äëÿ FAT12: çàãðóæàåò â ïàìÿòü ïåðâóþ êîïèþ òàáëèöû FAT ïî àäðåñó 6000:0000.
Åñëè ðàçìåð, óêàçàííûé â BPB, ïðåâîñõîäèò 12 ñåêòîðîâ,
ýòî îçíà÷àåò, ÷òî çàÿâëåííûé ðàçìåð ñëèøêîì áîëüøîé (ýòî íå ñ÷èòàåòñÿ
îøèáêîé ôàéëîâîé ñèñòåìû), è ÷èòàþòñÿ òîëüêî 12 ñåêòîðîâ (òàáëèöà FAT12
çàâåäîìî âëåçàåò â òàêîé îáú¸ì äàííûõ).
Äëÿ FAT16: èíèöèàëèçèðóåò âíóòðåííèå äàííûå, óêàçûâàÿ, ÷òî íèêàêîé ñåêòîð
FAT íå çàãðóæåí (îíè áóäóò ïîäãðóæàòüñÿ ïîçäíåå, êîãäà ïîíàäîáÿòñÿ
è òîëüêî òå, êîòîðûå ïîíàäîáÿòñÿ).
5. Åñëè êëàñòåð ðàâåí ñåêòîðó, òî áóòñåêòîð çàãðóçèë òîëüêî ÷àñòü ôàéëà
kordldr.f1x, è çàãðóç÷èê ïîäãðóæàåò âòîðóþ ñâîþ ÷àñòü, èñïîëüçóÿ
çíà÷åíèÿ ðåãèñòðîâ íà âõîäå â kordldr.f1x.
6. Çàãðóæàåò âòîðè÷íûé çàãðóç÷èê kord/loader ïî àäðåñó 1000:0000. Åñëè ôàéë íå
íàéäåí, èëè îêàçàëñÿ ïàïêîé, èëè îêàçàëñÿ ñëèøêîì áîëüøèì, òî ïåðåõîäèò
íà êîä îáðàáîòêè îøèáîê èç áóòñåêòîðà ñ ñîîáùåíèåì
"Fatal error: cannot load the secondary loader".
Çàìå÷àíèå: íà ýòîì ýòàïå èìÿ ôàéëà óæå ìîæíî óêàçûâàòü âìåñòå ñ ïóò¸ì
è â ôîðìàòå ASCIIZ, õîòÿ ïîääåðæêè äëèííûõ èì¸í è íåàíãëèéñêèõ ñèìâîëîâ
ïî-ïðåæíåìó íåò.
7. Èçìåíÿåò êîä îáðàáîòêè îøèáîê áóòñåêòîðà íà ïåðåõîä íà ìåòêó hooked_err.
Ýòî íóæíî, ÷òîáû ïîñëåäóþùèå îáðàùåíèÿ ê êîäó áóòñåêòîðà â ñëó÷àå
îøèáîê ÷òåíèÿ íå âûâîäèë ñîîòâåòñòâóþùåå ñîîáùåíèå ñ ïîñëåäóþùåé
ïåðåçàãðóçêîé, à ðàïîðòîâàë îá îøèáêå ÷òåíèÿ, êîòîðóþ ìîã áû
êàê-íèáóäü îáðàáîòàòü âòîðè÷íûé çàãðóç÷èê.
8. Åñëè çàãðóçî÷íûé äèñê èìååò èäåíòèôèêàòîð ìåíüøå 0x80,
òî óñòàíàâëèâàåò al='f' ("floppy"), ah=èäåíòèôèêàòîð äèñêà,
èíà÷å al='h' ("hard"), ah=èäåíòèôèêàòîð äèñêà-0x80 (íîìåð äèñêà).
Óñòàíàâëèâàåò bx='12', åñëè òèï ôàéëîâîé ñèñòåìû - FAT12, è
bx='16' â ñëó÷àå FAT16. Óñòàíàâëèâàåò si=ñìåùåíèå ôóíêöèè îáðàòíîãî
âûçîâà. Ïîñêîëüêó â ýòîò ìîìåíò ds=0, òî ds:si îáðàçóþò ïîëíûé àäðåñ.
9. Ïåðåäà¸ò óïðàâëåíèå ïî àäðåñó 1000:0000.
 
Ôóíêöèÿ îáðàòíîãî âûçîâà äëÿ âòîðè÷íîãî çàãðóç÷èêà:
ïðåäîñòàâëÿåò âîçìîæíîñòü ÷òåíèÿ ôàéëà.
Âõîä è âûõîä îïèñàíû â ñïåöèôèêàöèè íà çàãðóç÷èê.
1. Ñîõðàíÿåò ñòåê âûçûâàþùåãî êîäà è óñòàíàâëèâàåò ñâîé ñòåê:
ss:sp = 0:(7C00-8), bp=7C00: ïàðà ss:bp ïðè ðàáîòå ñ îñòàëüíûì
êîäîì äîëæíà óêàçûâàòü íà 0:7C00, à -8 áåð¸òñÿ îò òîãî, ÷òî
èíèöèàëèçèðóþùèé êîä áóòñåêòîðà óæå ïîìåñòèë â ñòåê 2 äâîéíûõ ñëîâà,
è îíè äîëæíû ñîõðàíÿòüñÿ â íåèçìåííîñòè.
2. Ðàçáèðàåò ïåðåäàííûå ïàðàìåòðû, âûÿñíÿåò, êàêîå äåéñòâèå çàïðîøåíî,
è âûçûâàåò íóæíóþ âñïîìîãàòåëüíóþ ïðîöåäóðó.
3. Âîññòàíàâëèâàåò ñòåê âûçûâàþùåãî êîäà è âîçâðàùàåò óïðàâëåíèå.
 
Âñïîìîãàòåëüíûå ïðîöåäóðû kordldr.f1x.
Ïðîöåäóðà ïîëó÷åíèÿ ñëåäóþùåãî êëàñòåðà â FAT (get_next_cluster):
1. Âñïîìèíàåò ðàçðÿäíîñòü FAT, âû÷èñëåííóþ ðàíåå.
Äëÿ FAT12:
2. Óñòàíàâëèâàåò ds = 0x6000 - ñåãìåíò, êóäà ðàíåå áûëà ñ÷èòàíà
âñÿ òàáëèöà FAT.
3. Ïîäñ÷èòûâàåò si = (êëàñòåð) + (êëàñòåð)/2 - ñìåùåíèå â ýòîì ñåãìåíòå
ñëîâà, çàäàþùåãî ñëåäóþùèé êëàñòåð. Çàãðóæàåò ñëîâî ïî ýòîìó àäðåñó.
4. Åñëè êëàñòåð èìååò íå÷¸òíûé íîìåð, òî ñîîòâåòñòâóþùèé åìó ýëåìåíò
ðàñïîëàãàåòñÿ â ñòàðøèõ 12 áèòàõ ñëîâà, è ñëîâî íóæíî ñäâèíóòü âïðàâî
íà 4 áèòà; â ïðîòèâíîì ñëó÷àå - â ìëàäøèõ 12 áèòàõ, è äåëàòü íè÷åãî íå
íàäî.
5. Âûäåëÿåò èç ïîëó÷èâøåãîñÿ ñëîâà 12 áèò. Ñðàâíèâàåò èõ ñ ïðåäåëîì 0xFF7:
íîìåðà íîðìàëüíûõ êëàñòåðîâ ìåíüøå, è ôëàã CF óñòàíàâëèâàåòñÿ;
ñïåöèàëüíûå çíà÷åíèÿ EOF è BadClus ñáðàñûâàþò ôëàã CF.
Äëÿ FAT16:
2. Âû÷èñëÿåò àäðåñ ïàìÿòè, ïðåäíàçíà÷åííîé äëÿ ñîîòâåòñòâóþùåãî ñåêòîðà äàííûõ
â òàáëèöå FAT.
3. Åñëè ñåêòîð åù¸ íå çàãðóæåí, òî çàãðóæàåò åãî.
4. Âû÷èñëÿåò ñìåùåíèå äàííûõ äëÿ êîíêðåòíîãî êëàñòåðà îòíîñèòåëüíî íà÷àëà
ñåêòîðà.
5. Çàãðóæàåò ñëîâî â ax èç àäðåñà, âû÷èñëåííîìó íà øàãàõ 1 è 3.
6. Ñðàâíèâàåò åãî ñ ïðåäåëîì 0xFFF7: íîìåðà íîðìàëüíûõ êëàñòåðîâ ìåíüøå, è ôëàã
CF óñòàíàâëèâàåòñÿ; ñïåöèàëüíûå çíà÷åíèÿ EOF è BadClus ñáðàñûâàþò CF.
 
Ïðîöåäóðà çàãðóçêè ôàéëà (load_file):
1. Òåêóùàÿ ðàññìàòðèâàåìàÿ ïàïêà - êîðíåâàÿ. Â öèêëå âûïîëíÿåò øàãè 2-4.
2. Êîíâåðòèðóåò èìÿ òåêóùåãî ðàññìàòðèâàåìîãî êîìïîíåíòà èìåíè (êîìïîíåíòû
ðàçäåëÿþòñÿ ñèìâîëîì '/') â FAT-ôîðìàò 8+3. Åñëè ýòî íåâîçìîæíî
(áîëüøå 8 ñèìâîëîâ â èìåíè, áîëüøå 3 ñèìâîëîâ â ðàñøèðåíèè èëè
áîëüøå îäíîé òî÷êè), âîçâðàùàåòñÿ ñ îøèáêîé.
3. Èùåò ýëåìåíò ñ òàêèì èìåíåì â òåêóùåé ðàññìàòðèâàåìîé ïàïêå. Äëÿ êîðíåâîé
ïàïêè èñïîëüçóåòñÿ ïðîöåäóðà èç áóòñåêòîðà. Äëÿ îñòàëüíûõ ïàïîê:
a) Ïðîâåðÿåò, åñòü ëè òàêàÿ ïàïêà â êýøå íåêîðíåâûõ ïàïîê.
(Èäåíòèôèêàöèÿ ïàïîê îñóùåñòâëÿåòñÿ ïî íîìåðó íà÷àëüíîãî êëàñòåðà.)
Åñëè òàêîé ïàïêè åù¸ íåò, äîáàâëÿåò å¸ â êýø; åñëè òîò ïåðåïîëíÿåòñÿ,
âûêèäûâàåò ïàïêó, ê êîòîðîé äîëüøå âñåãî íå áûëî îáðàùåíèé. (Äëÿ
êàæäîãî ýëåìåíòà êýøà õðàíèòñÿ ìåòêà îò 0 äî (ðàçìåð êýøà)-1,
îïðåäåëÿþùàÿ åãî íîìåð ïðè ñîðòèðîâêå ïî äàâíîñòè ïîñëåäíåãî îáðàùåíèÿ.
Ïðè îáðàùåíèè ê êàêîìó-òî ýëåìåíòó åãî ìåòêà ñòàíîâèòñÿ íóëåâîé,
à òå ìåòêè, êîòîðûå ìåíüøå ñòàðîãî çíà÷åíèÿ, óâåëè÷èâàþòñÿ íà åäèíèöó.)
á) Ïðîñìàòðèâàåò â ïîèñêàõ çàïðîøåííîãî èìåíè âñå ýëåìåíòû èç êýøà,
èñïîëüçóÿ ïðîöåäóðó èç áóòñåêòîðà. Åñëè îáíàðóæèâàåò èñêîìûé ýëåìåíò,
ïåðåõîäèò ê øàãó 4. Åñëè îáíàðóæèâàåò êîíåö ïàïêè, âîçâðàùàåòñÿ èç
ïðîöåäóðû ñ îøèáêîé.
â)  öèêëå ñ÷èòûâàåò ïàïêó ïîñåêòîðíî. Ïðè ýòîì ïðîïóñêàåò íà÷àëüíûå
ñåêòîðû, êîòîðûå óæå íàõîäÿòñÿ â êýøå è óæå áûëè ïðîñìîòðåíû. Êàæäûé
ïðî÷èòàííûé ñåêòîð êîïèðóåò â êýø, åñëè òàì åù¸ îñòà¸òñÿ ìåñòî,
è ïðîñìàòðèâàåò â í¸ì âñå ýëåìåíòû. Ðàáîòàåò, ïîêà íå ñëó÷èòñÿ îäíî èç
òð¸õ ñîáûòèé: íàéäåí èñêîìûé ýëåìåíò; êîí÷èëèñü êëàñòåðû (ñóäÿ ïî
öåïî÷êå êëàñòåðîâ â FAT); î÷åðåäíîé ýëåìåíò ïàïêè ñèãíàëèçèðóåò î êîíöå
(ïåðâûé áàéò íóëåâîé).  äâóõ ïîñëåäíèõ ñëó÷àÿõ âîçâðàùàåòñÿ ñ îøèáêîé.
4. Ïðîâåðÿåò òèï íàéäåííîãî ýëåìåíòà (ôàéë/ïàïêà): ïîñëåäíèé ýëåìåíò â
çàïðîøåííîì èìåíè äîëæåí áûòü ôàéëîì, âñå ïðîìåæóòî÷íûå - ïàïêàìè.
Åñëè òåêóùèé êîìïîíåíò èìåíè - ïðîìåæóòî÷íûé, ïðîäâèãàåò òåêóùóþ
ðàññìàòðèâàåìóþ ïàïêó è âîçâðàùàåòñÿ ê ïóíêòó 2.
5. Ïðîõîäèò ïî öåïî÷êå êëàñòåðîâ â FAT è ñ÷èòûâàåò âñå êëàñòåðû â óêàçàííûé
ïðè âûçîâå áóôåð ïîñëåäîâàòåëüíûìè âûçîâàìè ôóíêöèè áóòñåêòîðà;
ïðè ýòîì åñëè íåñêîëüêî êëàñòåðîâ ôàéëà ðàñïîëîæåíû íà äèñêå
ïîñëåäîâàòåëüíî, òî èõ ÷òåíèå îáúåäèíÿåòñÿ â îäíó îïåðàöèþ.
Ñëåäèò çà òåì, ÷òîáû íå ïðåâûñèòü óêàçàííûé ïðè âûçîâå ïðîöåäóðû
ëèìèò ÷èñëà ñåêòîðîâ äëÿ ÷òåíèÿ.
 
Ïðîöåäóðà ïðîäîëæåíèÿ çàãðóçêè ôàéëà (continue_load_file): âñòðîåíà
âíóòðü øàãà 5 load_file; çàãðóæàåò â ðåãèñòðû íóæíûå çíà÷åíèÿ (ðàíåå
ñîõðàí¸ííûå èç load_file) è ïðîäîëæàåò øàã 5.
/kernel/trunk/sec_loader/trunk/boot/fat1x/kordldr.f1x.asm
0,0 → 1,667
; 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 <organization> 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 <Lrz> ''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 <copyright holder> 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.
;*****************************************************************************
 
org 0x7E00
; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here
; ss:bp = 0:7C00
virtual at bp
rb 3 ; BS_jmpBoot
rb 8 ; BS_OEMName, ignored
dw ? ; BPB_BytsPerSec
BPB_SecsPerClus db ?
BPB_RsvdSecCnt dw ?
BPB_NumFATs db ?
BPB_RootEntCnt dw ?
BPB_TotSec16 dw ?
db ? ; BPB_Media
BPB_FATSz16 dw ?
BPB_SecPerTrk dw ?
BPB_NumHeads dw ?
BPB_HiddSec dd ?
BPB_TotSec32 dd ?
BS_DrvNum db ?
fat_type db ? ; this is BS_Reserved1,
; we use it to save FS type: 0=FAT12, 1=FAT16
db ? ; BS_BootSig
num_sectors dd ? ; BS_VolID
; rb 11 ; BS_VolLab
; rb 3 ; BS_FilSysType, first 3 bytes
read_sectors dw ?
read_sectors2 dw ?
lookup_in_root_dir dw ?
scan_for_filename dw ?
err dw ?
noloader dw ?
cachelimit dw ?
filesize: ; will be used to save file size
rb 5 ; BS_FilSysType, last 5 bytes
; following variables are located in the place of starting code;
; starting code is no more used at this point
sect_per_clus dw ?
cur_cluster dw ?
next_cluster dw ?
flags dw ?
cur_delta dd ?
end virtual
 
; procedures from boot sector
; LBA version
lba_read_sectors = 7CE2h
lba_read_sectors2 = 7CDCh
lba_lookup_in_root_dir = 7D4Fh
lba_scan_for_filename = 7D2Dh
lba_err = 7CB5h
lba_noloader = 7CB2h
; CHS version
chs_read_sectors = 7CDEh
chs_read_sectors2 = 7CD8h
chs_lookup_in_root_dir = 7D70h
chs_scan_for_filename = 7D4Eh
chs_err = 7CB1h
chs_noloader = 7CAEh
 
push ax cx ; save our position on disk
push ss
pop es
; determine version of bootsector (LBA vs CHS)
; mov [read_sectors], chs_read_sectors
; mov [read_sectors2], chs_read_sectors2
; mov [lookup_in_root_dir], chs_lookup_in_root_dir
; mov [scan_for_filename], chs_scan_for_filename
; mov [err], chs_err
; mov [noloader], chs_noloader
lea di, [read_sectors]
mov si, chs_proc_addresses
mov cx, 6*2
cmp word [chs_scan_for_filename], 0xFF31 ; 'xor di,di'
jz @f
add si, cx
; mov [read_sectors], lba_read_sectors
; mov [read_sectors2], lba_read_sectors2
; mov [lookup_in_root_dir], lba_lookup_in_root_dir
; mov [scan_for_filename], lba_scan_for_filename
; mov [err], lba_err
; mov [noloader], lba_noloader
@@:
rep movsb
mov cl, [BPB_SecsPerClus]
mov [sect_per_clus], cx
xor bx, bx
; determine size of cache for folders
int 12h ; ax = size of available base memory in Kb
sub ax, 94000h / 1024
jae @f
nomem:
mov si, nomem_str
jmp [err]
@@:
shr ax, 3
mov [cachelimit], ax ; size of cache - 1
; get type of file system - FAT12 or FAT16?
; calculate number of clusters
mov ax, [BPB_TotSec16]
xor dx, dx
test ax, ax
jnz @f
mov ax, word [BPB_TotSec32]
mov dx, word [BPB_TotSec32+2]
@@:
sub ax, [bp-8] ; dword [bp-8] = first data sector
sbb dx, [bp-6]
jb j_noloader
div [sect_per_clus]
; ax = number of clusters
; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes
mov [fat_type], ch
cmp ax, 0xFF5
jb init_fat12
inc [fat_type]
init_fat16:
; no sectors loaded
mov di, 0x8200
xor ax, ax
mov cx, 0x100/2
rep stosw
jmp init_fat_done
init_fat12:
; read FAT
push 0x6000
pop es
mov ax, [BPB_RsvdSecCnt]
mov cx, [BPB_FATSz16]
cmp cx, 12
jb @f
mov cx, 12
@@:
xor dx, dx
call [read_sectors]
init_fat_done:
; if cluster = sector, we need to read second part of our file
; (bootsector loads only first cluster of kordldr.f1x)
pop cx ax ; restore our position on disk
cmp cx, 1
ja kordldr_full
sub ax, [bp-8]
inc ax
inc ax ; ax = first cluster of kordldr.f12
call get_next_cluster
jc @f
j_noloader:
jmp [noloader]
@@:
dec ax
dec ax
push 0x800
pop es
call [read_sectors2]
kordldr_full:
; ...continue loading...
mov di, secondary_loader_info
call load_file
test bx, bx
mov bx, [err]
jz @f
mov si, aKernelNotFound
jmp bx
@@:
; for subsequent calls to callback function, hook error handler
; mov byte [bx], 0xE9 ; 'jmp' opcode
; mov ax, hooked_err - 3
; sub ax, bx
; mov word [bx+1], ax
; push hooked_err / ret
mov word [bx], 0x68 + ((hooked_err and 0xFF) shl 8)
mov word [bx+2], (hooked_err shr 8) + (0xC3 shl 8)
; set registers for secondary loader
mov ah, [BS_DrvNum]
mov al, 'f'
test ah, ah
jns @f
sub ah, 80h
mov al, 'h'
@@:
mov bx, '12'
cmp [fat_type], 0
jz @f
mov bh, '6'
@@:
mov si, callback ; ds:si = far pointer to callback procedure
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000
 
nomem_str db 'No memory',0
 
chs_proc_addresses:
dw chs_read_sectors
dw chs_read_sectors2
dw chs_lookup_in_root_dir
dw chs_scan_for_filename
dw chs_err
dw chs_noloader
lba_proc_addresses:
dw lba_read_sectors
dw lba_read_sectors2
dw lba_lookup_in_root_dir
dw lba_scan_for_filename
dw lba_err
dw lba_noloader
 
get_next_cluster:
; in: ax = cluster
; out: if there is next cluster: CF=1, ax = next cluster
; out: if there is no next cluster: CF=0
push si
cmp [fat_type], 0
jnz gnc16
; for FAT12
push ds
push 0x6000
pop ds
mov si, ax
shr si, 1
add si, ax
test al, 1
lodsw
jz @f
shr ax, 4
@@:
and ax, 0xFFF
cmp ax, 0xFF7
pop ds si
ret
; for FAT16
gnc16:
; each sector contains 200h bytes = 100h FAT entries
; so ah = # of sector, al = offset in sector
mov si, ax
mov ah, 0
shr si, 8
; calculate segment for this sector of FAT table
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si)
; segment = 6000 + 20*si, offset = 0
push es
push si
shl si, 5
add si, 0x6000
mov es, si
pop si
cmp byte [ss:0x8200+si], ah ; sector already loaded?
jnz @f
; load corresponding sector
pusha
push es
xor bx, bx
mov ax, [BPB_RsvdSecCnt]
xor dx, dx
add ax, si
adc dx, bx
mov cx, 1 ; read 1 sector
call [read_sectors]
pop es
popa
@@:
mov si, ax
add si, si
; mov ax, [es:si]
lods word [es:si]
pop es
cmp ax, 0xFFF7
pop si
ret
 
if $ > 0x8000
error 'get_next_cluster must fit in first sector of kordldr.f1x!'
end if
 
load_file:
; in: ss:bp = 0:7C00
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; ASCIIZ name
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found
; out: dx:ax = file size (0xFFFFFFFF if file not found)
xor ax, ax ; start from root directory
mov dx, -1
mov word [filesize], dx
mov word [filesize+2], dx ; initialize file size with invalid value
lea si, [di+6]
parse_dir_loop:
; convert name to FAT name
push di
push ax
push ss
pop es
; convert ASCIIZ filename to FAT name
mov di, filename
push di
mov cx, 8+3
mov al, ' '
rep stosb
pop di
mov cl, 8 ; 8 symbols per name
mov bl, 1
nameloop:
lodsb
test al, al
jz namedone
cmp al, '/'
jz namedone
cmp al, '.'
jz namedot
dec cx
js badname
cmp al, 'a'
jb @f
cmp al, 'z'
ja @f
sub al, 'a'-'A'
@@:
stosb
jmp nameloop
namedot:
inc bx
jp badname
add di, cx
mov cl, 3
jmp nameloop
badname: ; do not make direct js/jp to notfound_pop:
; this generates long forms of conditional jumps and results in longer code
jmp notfound_pop
namedone:
; scan directory
pop ax ; ax = cluster of directory or 0 for root
push ds
push si
push es
pop ds
mov si, filename ; ds:si -> filename in FAT style
test ax, ax
jnz lookup_in_notroot_dir
; for root directory, use the subroutine from bootsector
call [lookup_in_root_dir]
jmp lookup_done
lookup_in_notroot_dir:
; for other directories, read a folder sector-by-sector and scan
; first, try to use the cache
push ds
push cs
pop ds
mov bx, [cachelimit]
add bx, bx
mov di, foldcache_mark
@@:
mov dx, [foldcache_clus+di-foldcache_mark+bx]
cmp dx, ax
jz cacheok
test dx, dx
jz cacheadd ; the cache has place for new entry
dec bx
dec bx
jns @b
; the folder is not present in the cache, so add it
; the cache is full; find the oldest entry and replace it with the new one
mov dx, [cachelimit]
@@:
inc bx
inc bx
cmp word [di+bx], dx ; marks have values 0 through [cachelimit]
jnz @b
cacheadd:
or word [di+bx], 0xFFFF ; very big value, it will be changed soon
mov [foldcache_clus+di-foldcache_mark+bx], ax
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet
cacheok:
; update cache marks
mov dx, [di+bx]
mov cx, [foldcache_size+di-foldcache_mark+bx]
mov di, [cachelimit]
add di, di
cacheupdate:
cmp [foldcache_mark+di], dx
adc [foldcache_mark+di], 0
dec di
dec di
jns cacheupdate
and [foldcache_mark+bx], 0
; done, bx contains (position in cache)*2
pop ds
; mov dx, bx
; shl dx, 8 ; dx = (position in cache)*0x2000/0x10
; add dx, 0x9200
lea dx, [bx+0x92]
xchg dl, dh
mov es, dx
jcxz not_in_cache
call [scan_for_filename]
jz lookup_done
not_in_cache:
; cache miss, read folder data from disk
mov bx, cx
shr bx, 4
shl cx, 5
mov di, cx ; es:di -> free space in cache entry
; external loop: scan clusters
folder_next_cluster:
; internal loop: scan sectors in cluster
mov cx, [sect_per_clus]
push ax
dec ax
dec ax
mul cx
add ax, [bp-8]
adc dx, [bp-6] ; dx:ax = absolute sector
folder_next_sector:
; skip first bx sectors
dec bx
jns folder_skip_sector
push cx
push es di
push 0x8000
pop es
xor bx, bx
mov cx, 1
push es
call [read_sectors]
; copy data to the cache...
pop ds
pop di es
cmp di, 0x2000 ; ...if there is free space, of course
jae @f
push si di
mov cx, 0x100
xor si, si
rep movsw
mov di, es
shr di, 8
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache
pop di si
@@:
push es
push 0x8000
pop es
push cs
pop ds
mov cx, 0x10
call [scan_for_filename]
pop es
pop cx
jz lookup_done_pop
folder_skip_sector:
inc ax
jnz @f
inc dx
@@:
loop folder_next_sector
pop ax ; ax = current cluster
call get_next_cluster
jc folder_next_cluster
stc
push ax
lookup_done_pop:
pop ax
lookup_done:
pop si
pop ds
; CF=1 <=> failed
jnc found
notfound:
pop di
mov bx, 2 ; file not found
mov ax, 0xFFFF
mov dx, ax ; invalid file size
ret
notfound_pop:
pop ax
jmp notfound
found:
mov ax, [es:di+26] ; get cluster
test byte [es:di+11], 10h ; directory?
jz regular_file
cmp byte [si-1], 0
jz notfound ; don't read directories as a regular files
; ok, we have found a directory and the caller requested a file into it
pop di
jmp parse_dir_loop ; restart with new cluster in ax
regular_file:
cmp byte [si-1], 0
jnz notfound ; file does not contain another files
; ok, we have found a regular file and the caller requested it
; save file size
mov dx, [es:di+28]
mov [filesize], dx
mov dx, [es:di+30]
mov [filesize+2], dx
pop di
mov si, [di+4]
shl si, 3
push si ; [ds:di+4] = limit in 4K blocks
les bx, [di] ; es:bx -> buffer
clusloop:
; ax = first cluster, top of stack contains limit in sectors
mov si, ax ; remember current cluster
xor cx, cx ; cx will contain number of consecutive clusters
mov word [cur_delta], cx
mov word [cur_delta+2], cx
mov di, ax
clusfind:
inc di
inc cx
call get_next_cluster
jnc clusread
cmp ax, di
jz clusfind
stc
clusread:
pop di ; limit in sectors
push ax ; save next cluster
pushf ; save flags
; read cx clusters, starting from si
; calculate number of sectors
xchg ax, cx
mul [sect_per_clus]
; dx:ax = number of sectors; compare with limit
mov word [num_sectors], ax
mov word [num_sectors+2], dx
jmp @f
continue_load_file:
les bx, [di] ; es:bx -> buffer
mov di, [di+4] ; ds:di = limit in 4K blocks
shl di, 3 ; now di = limit in sectors
mov ax, word [num_sectors]
mov dx, word [num_sectors+2]
mov si, [cur_cluster]
push [next_cluster]
push [flags]
or ax, dx
jz nextclus
@@:
test dx, dx
jnz clusdecrease
push dx ; limit was not exceeded
cmp ax, di
jbe @f
pop ax
clusdecrease:
push 1 ; limit was exceeded
mov ax, di
@@:
sub di, ax ; calculate new limit
sub word [num_sectors], ax
sbb word [num_sectors+2], 0
; calculate starting sector
xchg ax, cx
lea ax, [si-2]
mul [sect_per_clus]
add ax, word [cur_delta]
adc dx, word [cur_delta+2]
add word [cur_delta], cx
adc word [cur_delta+2], 0
; read
call [read_sectors2]
pop dx
; next cluster?
nextclus:
popf
pop ax
mov [cur_cluster], si
mov [next_cluster], ax
pushf
pop [flags]
jnc @f ; no next cluster => return
mov dl, 1 ; dh=0 in any case
test di, di
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded
push di
jmp clusloop ; all is ok, continue
hooked_err:
mov sp, 7C00h-12-2 ; restore stack
mov dx, 3 ; return: read error
@@:
mov bx, dx
mov ax, [filesize]
mov dx, [filesize+2]
ret
 
; Callback function for secondary loader
callback:
; in: ax = function number; only functions 1 and 2 are defined for now
; save caller's stack
mov dx, ss
mov cx, sp
; set our stack (required because we need ss=0)
xor si, si
mov ss, si
mov sp, 7C00h-8
mov bp, 7C00h
push dx
push cx
; call our function
stc ; unsupported function
dec ax
jz callback_readfile
dec ax
jnz callback_ret
; function 2: continue loading file
; can be called only after function 1 returned value bx=1 (only part of file was loaded)
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error
; out: dx:ax = file size
call continue_load_file
jmp callback_ret_succ
callback_readfile:
; function 1: read file
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; ASCIIZ name
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error
; out: dx:ax = file size (0xFFFFFFFF if file was not found)
call load_file
callback_ret_succ:
clc ; function is supported
callback_ret:
; restore caller's stack
pop cx
pop ss
mov sp, cx
; return to caller
retf
 
secondary_loader_info:
dw 0, 0x1000
dw 0x30000 / 0x1000
db 'kord/loader',0
aKernelNotFound db 'Fatal error: cannot load the secondary loader',0
 
foldcache_clus dw 0,0,0,0,0,0,0 ; start with no folders in cache
foldcache_mark rw 7
foldcache_size rw 7
filename rb 11
if $ > 0x8200
error: table overwritten
end if
/kernel/trunk/sec_loader/trunk/boot/fat1x/.
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property