Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 2464 → Rev 2465

/kernel/branches/Kolibri-acpi/bootloader/extended_primary_loader/fat32/bootsect.asm
0,0 → 1,358
; 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
; 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
/kernel/branches/Kolibri-acpi/bootloader/extended_primary_loader/fat32/bootsect.txt
0,0 → 1,333
; 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.
;*****************************************************************************
 
×èòàé ìåæäó ñòðîê - òàì íèêîãäà íå áûâàåò îïå÷àòîê.
 
Áóòñåêòîð äëÿ FAT32-òîìà íà íîñèòåëå ñ ðàçìåðîì ñåêòîðà 0x200 = 512 áàéò.
 
=====================================================================
 
Åñòü äâå âåðñèè â çàâèñèìîñòè îò òîãî, ïîääåðæèâàåò ëè íîñèòåëü LBA,
âûáîð îñóùåñòâëÿåòñÿ óñòàíîâêîé êîíñòàíòû use_lba â ïåðâîé ñòðîêå èñõîäíèêà.
Òðåáîâàíèÿ äëÿ ðàáîòû:
1) Ñàì áóòñåêòîð, ïåðâàÿ êîïèÿ FAT è âñå èñïîëüçóåìûå ôàéëû
äîëæíû áûòü ÷èòàáåëüíû. (Åñëè äåëî ïðîèñõîäèò íà íîñèòåëå ñ ðàçáèåíèåì íà
ðàçäåëû è çàãðóçî÷íûé êîä â MBR äîñòàòî÷íî óìíûé, òî ÷èòàáåëüíîñòè ðåçåðâíîé
êîïèè áóòñåêòîðà (ñåêòîð íîìåð 6 íà òîìå) äîñòàòî÷íî âìåñòî ÷èòàáåëüíîñòè
ñàìîãî áóòñåêòîðà).
2) Ìèíèìàëüíûé ïðîöåññîð - 80386.
3) Â ñèñòåìå äîëæíî áûòü êàê ìèíèìóì 584K ñâîáîäíîé áàçîâîé ïàìÿòè.
 
=====================================================================
 
Äîêóìåíòàöèÿ â òåìó (ññûëêè ïðîâåðÿëèñü íà âàëèäíîñòü 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
 
=====================================================================
 
Ñõåìà èñïîëüçóåìîé ïàìÿòè:
...-7C00 ñòåê
7C00-7E00 êîä áóòñåêòîðà
7E00-8200 âñïîìîãàòåëüíûé ôàéë çàãðóç÷èêà (kordldr.f32)
8400-8C00 èíôîðìàöèÿ î êýøå äëÿ òàáëèöû FAT: 100h âõîäîâ ïî 8
áàéò: 4 áàéòà (äâå ññûëêè - âïåð¸ä è íàçàä) äëÿ
îðãàíèçàöèè L2-ñïèñêà âñåõ ïðî÷èòàííûõ ñåêòîðîâ â
ïîðÿäêå âîçðàñòàíèÿ ïîñëåäíåãî âðåìåíè èñïîëüçîâàíèÿ
+ 4 áàéòà äëÿ íîìåðà ñåêòîðà; ïðè ïåðåïîëíåíèè êýøà
âûêèäûâàåòñÿ ýëåìåíò èç ãîëîâû ñïèñêà, òî åñòü òîò,
ê êîòîðîìó äîëüøå âñåõ íå áûëî îáðàùåíèé
60000-80000 êýø äëÿ òàáëèöû FAT (100h ñåêòîðîâ)
80000-90000 òåêóùèé êëàñòåð òåêóùåé ðàññìàòðèâàåìîé ïàïêè
90000-... êýø äëÿ ñîäåðæèìîãî ïàïîê (êàæäîé ïàïêå îòâîäèòñÿ
2000h áàéò = 100h âõîäîâ, îäíîâðåìåííî â êýøå
ìîæåò íàõîäèòüñÿ íå áîëåå 8 ïàïîê;
òî÷íûé ðàçìåð îïðåäåëÿåòñÿ ðàçìåðîì äîñòóïíîé
ôèçè÷åñêîé ïàìÿòè - êàê ïðàâèëî, íåïîñðåäñòâåííî
ïåðåä A0000 ðàçìåùàåòñÿ EBDA, Extended BIOS Data Area)
 
=====================================================================
 
Îñíîâíîé ïðîöåññ çàãðóçêè.
Òî÷êà âõîäà (start): ïîëó÷àåò óïðàâëåíèå îò BIOS ïðè çàãðóçêå, ïðè ýòîì
dl ñîäåðæèò èäåíòèôèêàòîð äèñêà, ñ êîòîðîãî èä¸ò çàãðóçêà
1. Íàñòðàèâàåò ñòåê ss:sp = 0:7C00 (ñòåê ðàñïîëàãàåòñÿ íåïîñðåäñòâåííî ïåðåä
êîäîì), ñåãìåíò äàííûõ ds = 0, è óñòàíàâëèâàåò ss:bp íà íà÷àëî
áóòñåêòîðà (â äàëüíåéøåì äàííûå áóäóò àäðåñîâàòüñÿ ÷åðåç [bp+N] -
ýòî îñâîáîæäàåò ds è ýêîíîìèò íà ðàçìåðå êîäà). Ñîõðàíÿåò â ñòåêå
èäåíòèôèêàòîð çàãðóçî÷íîãî äèñêà äëÿ ïîñëåäóþùåãî îáðàùåíèÿ
÷åðåç byte [bp-2].
2. LBA-âåðñèÿ: ïðîâåðÿåò, ïîääåðæèâàåò ëè íîñèòåëü LBA, âûçîâîì ôóíêöèè 41h
ïðåðûâàíèÿ 13h. Åñëè íåò, ïåðåõîäèò íà êîä îáðàáîòêè îøèáîê ñ
ñîîáùåíèåì îá îòñóòñòâèè LBA.
CHS-âåðñèÿ: îïðåäåëÿåò ãåîìåòðèþ íîñèòåëÿ âûçîâîì ôóíêöèè 8 ïðåðûâàíèÿ 13h è
çàïèñûâàåò ïîëó÷åííûå äàííûå ïîâåðõ BPB. Åñëè âûçîâ çàâåðøèëñÿ îøèáêîé,
ïðåäïîëàãàåò óæå ñóùåñòâóþùèå äàííûå êîððåêòíûìè.
3. Âû÷èñëÿåò íà÷àëî äàííûõ FAT-òîìà, ñîõðàíÿåò åãî â ñòåê äëÿ ïîñëåäóþùåãî
îáðàùåíèÿ ÷åðåç dword [bp-10].  ïðîöåññå âû÷èñëåíèÿ óçíà¸ò íà÷àëî
ïåðâîé FAT, ñîõðàíÿåò è åãî â ñòåê äëÿ ïîñëåäóþùåãî îáðàùåíèÿ ÷åðåç
dword [bp-6].
4. (Çàêàí÷èâàÿ òåìó ïàðàìåòðîâ â ñòåêå) Ïîìåùàåò â ñòåê dword-çíà÷åíèå -1
äëÿ ïîñëåäóþùåãî îáðàùåíèÿ ÷åðåç dword [bp-14] - èíèöèàëèçàöèÿ
ïåðåìåííîé, ñîäåðæàùåé òåêóùèé ñåêòîð, íàõîäÿùèéñÿ â êýøå FAT
(-1 íå ÿâëÿåòñÿ âàëèäíûì çíà÷åíèåì äëÿ íîìåðà ñåêòîðà FAT).
5. Èùåò â êîðíåâîé ïàïêå ýëåìåíò kordldr.f32. Åñëè íå íàõîäèò - ïåðåõîäèò íà
êîä îáðàáîòêè îøèáîê ñ ñîîáùåíèåì î íåíàéäåííîì çàãðóç÷èêå.
Çàìå÷àíèå: íà ýòîì ýòàïå çàãðóçêè èñêàòü ìîæíî òîëüêî â êîðíåâîé
ïàïêå è òîëüêî èìåíà, çàäàííûå â ôîðìàòå ôàéëîâîé ñèñòåìå FAT
(8+3 - 8 áàéò íà èìÿ, 3 áàéòà íà ðàñøèðåíèå, âñå áóêâû äîëæíû
áûòü çàãëàâíûìè, ïðè íåîáõîäèìîñòè èìÿ è ðàñøèðåíèå äîïîëíÿþòñÿ
ïðîáåëàìè, ðàçäåëÿþùåé òî÷êè íåò, çàâåðøàþùåãî íóëÿ íåò).
6. Çàãðóæàåò ïåðâûé êëàñòåð ôàéëà kordldr.f32 ïî àäðåñó 0:7E00 è ïåðåäà¸ò
åìó óïðàâëåíèå. Ïðè ýòîì â ðåãèñòðå eax îêàçûâàåòñÿ àáñîëþòíûé
íîìåð ïåðâîãî ñåêòîðà kordldr.f32, à â cx - ÷èñëî ñ÷èòàííûõ ñåêòîðîâ
(ðàâíîå ðàçìåðó êëàñòåðà).
 
Âñïîìîãàòåëüíûå ïðîöåäóðû áóòñåêòîðà.
Êîä îáðàáîòêè îøèáîê (err):
1. Âûâîäèò ñòðîêó ñ ñîîáùåíèåì îá îøèáêå.
2. Âûâîäèò ñòðîêó "Press any key...".
3. Æä¸ò íàæàòèÿ any key.
4. Âûçûâàåò int 18h, äàâàÿ øàíñ BIOSó ïîïûòàòüñÿ çàãðóçèòüñÿ îòêóäà-íèáóäü åù¸.
5. Äëÿ ïîäñòðàõîâêè çàöèêëèâàåòñÿ.
 
Ïðîöåäóðà ÷òåíèÿ êëàñòåðà (read_cluster):
íà âõîäå äîëæíî áûòü óñòàíîâëåíî:
ss:bp = 0:7C00
es:bx = óêàçàòåëü íà íà÷àëî áóôåðà, êóäà áóäóò ïðî÷èòàíû äàííûå
eax = íîìåð êëàñòåðà
íà âûõîäå: ecx = ÷èñëî ïðî÷èòàííûõ ñåêòîðîâ (ðàçìåð êëàñòåðà),
es:bx óêàçûâàåò íà êîíåö áóôåðà, â êîòîðûé áûëè ïðî÷èòàíû äàííûå,
eax è ñòàðøèå ñëîâà äðóãèõ 32-áèòíûõ ðåãèñòðîâ ðàçðóøàþòñÿ
Çàãðóæàåò â ecx ðàçìåð êëàñòåðà, ïåðåêîäèðóåò íîìåð êëàñòåðà â íîìåð ñåêòîðà
è ïåðåõîäèò ê ñëåäóþùåé ïðîöåäóðå.
 
Ïðîöåäóðà ÷òåíèÿ ñåêòîðîâ (read_sectors32 è read_sectors2):
íà âõîäå äîëæíî áûòü óñòàíîâëåíî:
ss:bp = 0:7C00
es:bx = óêàçàòåëü íà íà÷àëî áóôåðà, êóäà áóäóò ïðî÷èòàíû äàííûå
eax = ñòàðòîâûé ñåêòîð (îòíîñèòåëüíî íà÷àëà ëîãè÷åñêîãî äèñêà
äëÿ read_sectors32, îòíîñèòåëüíî íà÷àëà äàííûõ
äëÿ read_sectors2)
cx = ÷èñëî ñåêòîðîâ (äîëæíî áûòü áîëüøå íóëÿ)
íà âûõîäå: es:bx óêàçûâàåò íà êîíåö áóôåðà, â êîòîðûé áûëè ïðî÷èòàíû äàííûå
ñòàðøèå ñëîâà 32-áèòíûõ ðåãèñòðîâ ìîãóò ðàçðóøèòüñÿ
0. Åñëè âûçûâàåòñÿ read_sectors2, îíà ïåðåâîäèò óêàçàííûé åé íîìåð ñåêòîðà
â íîìåð îòíîñèòåëüíî íà÷àëà ëîãè÷åñêîãî äèñêà, ïðèáàâëÿÿ íîìåð ñåêòîðà
íà÷àëà äàííûõ, õðàíÿùèéñÿ â ñòåêå êàê [bp-10].
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.
 
Ïðîöåäóðà ïîèñêà ýëåìåíòà â ïàïêå (lookup_in_dir):
íà âõîäå äîëæíî áûòü óñòàíîâëåíî:
ss:bp = 0:7C00
ds:si = óêàçàòåëü íà èìÿ ôàéëà â ôîðìàòå FAT (ñì. âûøå)
eax = íà÷àëüíûé êëàñòåð ïàïêè
bx = 0
íà âûõîäå: ôëàã CF îïðåäåëÿåò, óäàëîñü ëè íàéòè ôàéë; åñëè óäàëîñü, òî
CF ñáðîøåí è es:di óêàçûâàåò íà ýëåìåíò ïàïêè
 öèêëå ñ÷èòûâàåò êëàñòåðû ïàïêè è èùåò çàïðîøåííûé ýëåìåíò â ïðî÷èòàííûõ
äàííûõ. Äëÿ ÷òåíèÿ êëàñòåðà èñïîëüçóåò óæå îïèñàííóþ ïðîöåäóðó read_clusters,
äëÿ ïðîäâèæåíèÿ ïî öåïî÷êå êëàñòåðîâ - îïèñàííóþ äàëåå ïðîöåäóðó
get_next_clusters. Äàííûå ÷èòàþòñÿ â îáëàñòü ïàìÿòè, íà÷èíàþùóþñÿ ñ àäðåñà
8000:0000, ïðè ýòîì ïåðâûå 2000h áàéò èç äàííûõ ïàïêè (ìîæåò áûòü, ìåíüøå,
åñëè ÷òåíèå ïðåðâ¸òñÿ ðàíüøå) íå ïåðåêðûâàþòñÿ ïîñëåäóþùèìè ÷òåíèÿìè
(ýòî áóäåò èñïîëüçîâàíî ïîçäíåå, â ñèñòåìå êýøèðîâàíèÿ èç kordldr.f32).
Âûõîä îñóùåñòâëÿåòñÿ â ëþáîì èç ñëåäóþùèõ ñëó÷àåâ: íàéäåí çàïðîøåííûé ýëåìåíò;
êîí÷èëèñü ýëåìåíòû â ïàïêå (ïåðâûé áàéò î÷åðåäíîãî ýëåìåíòà íóëåâîé);
êîí÷èëèñü äàííûå ïàïêè â ñîîòâåòñòâèè ñ öåïî÷êîé êëàñòåðîâ èç FAT.
 
Ïðîöåäóðà âûâîäà íà ýêðàí ASCIIZ-ñòðîêè (out_string):
íà âõîäå: ds:si -> ñòðîêà
 öèêëå, ïîêà íå äîñòèãíóò çàâåðøàþùèé íîëü, âûçûâàåò ôóíêöèþ int 10h/ah=0Eh.
 
=====================================================================
 
Ðàáîòà âñïîìîãàòåëüíîãî çàãðóç÷èêà kordldr.f32:
1. Îïðåäåëÿåò, áûë ëè îí çàãðóæåí CHS- èëè LBA-âåðñèåé áóòñåêòîðà.
 çàâèñèìîñòè îò ýòîãî óñòàíàâëèâàåò ñìåùåíèÿ èñïîëüçóåìûõ ïðîöåäóð
áóòñåêòîðà. Êðèòåðèé ïðîâåðêè: â CHS-âåðñèè ïî àäðåñó err íàõîäèòñÿ
áàéò 0xE8 (ìàøèííàÿ êîìàíäà call), â LBA-âåðñèè ïî òîìó æå àäðåñó
íàõîäèòñÿ áàéò 0x14, à àäðåñ ïðîöåäóðû err äðóãîé.
2. Óçíà¸ò ðàçìåð ñâîáîäíîé áàçîâîé ïàìÿòè (ò.å. ñâîáîäíîãî íåïðåðûâíîãî êóñêà
àäðåñîâ ïàìÿòè, íà÷èíàþùåãîñÿ ñ 0) âûçîâîì int 12h.  ñîîòâåòñòâèè ñ
íèì âû÷èñëÿåò ÷èñëî ýëåìåíòîâ â êýøå ïàïîê. Õîòÿ áû äëÿ îäíîãî ýëåìåíòà
ìåñòî äîëæíî áûòü, îòñþäà îãðàíè÷åíèå â 592 Kb (94000h áàéò).
Çàìå÷àíèå: ýòîò ðàçìåð íå ìîæåò ïðåâîñõîäèòü 0A0000h áàéò è
íà ïðàêòèêå îêàçûâàåòñÿ íåìíîãî (íà 1-2 êèëîáàéòà) ìåíüøèì èç-çà
íàëè÷èÿ äîïîëíèòåëüíîé îáëàñòè äàííûõ BIOS "ââåðõó" áàçîâîé ïàìÿòè.
3. Èíèöèàëèçèðóåò êýøèðîâàíèå ïàïîê. Áóòñåêòîð óæå çàãðóçèë êàêóþ-òî ÷àñòü
äàííûõ êîðíåâîé ïàïêè; êîïèðóåò çàãðóæåííûå äàííûå â êýø è çàïîìèíàåò,
÷òî â êýøå åñòü êîðíåâàÿ ïàïêà.
4. Èíèöèàëèçèðóåò êýøèðîâàíèå FAT. Áóòñåêòîð èìååò äåëî ñ FAT â òîì è òîëüêî
òîì ñëó÷àå, êîãäà åìó ïðèõîäèòñÿ çàãðóæàòü äàííûå êîðíåâîé ïàïêè,
íå ïîìåñòèâøèåñÿ â îäèí êëàñòåð.  ýòîì ñëó÷àå â ïàìÿòè ïðèñóòñòâóåò
îäèí ñåêòîð FAT (åñëè áûëî íåñêîëüêî îáðàùåíèé - ïîñëåäíèé èç
èñïîëüçîâàííûõ).
5. Åñëè êëàñòåð ðàâåí ñåêòîðó, òî áóòñåêòîð çàãðóçèë òîëüêî ÷àñòü ôàéëà
kordldr.f32, è çàãðóç÷èê ïîäãðóæàåò âòîðóþ ñâîþ ÷àñòü, èñïîëüçóÿ
çíà÷åíèÿ ðåãèñòðîâ íà âõîäå â kordldr.f32.
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 (íîìåð äèñêà).
(Ãîâîðèòå, äèñêåòîê ñ FAT32 íå áûâàåò?  ÷¸ì-òî Âû ïðàâû... íî
óâåðåíû ëè Âû, ÷òî íåò çàãðóçî÷íûõ óñòðîéñòâ, ïîäîáíûõ äèñêåòàì,
íî áîëüøåãî ðàçìåðà, è äëÿ êîòîðûõ BIOS-èäåíòèôèêàòîð ìåíüøå 0x80?)
Óñòàíàâëèâàåò bx='32' (òèï ôàéëîâîé ñèñòåìû - FAT32).
Óñòàíàâëèâàåò si=ñìåùåíèå ôóíêöèè îáðàòíîãî âûçîâà. Ïîñêîëüêó â ýòîò
ìîìåíò ds=0, òî ds:si îáðàçóþò ïîëíûé àäðåñ.
9. Ïåðåäà¸ò óïðàâëåíèå ïî àäðåñó 1000:0000.
 
Ôóíêöèÿ îáðàòíîãî âûçîâà äëÿ âòîðè÷íîãî çàãðóç÷èêà:
ïðåäîñòàâëÿåò âîçìîæíîñòü ÷òåíèÿ ôàéëà.
Âõîä è âûõîä îïèñàíû â ñïåöèôèêàöèè íà çàãðóç÷èê.
1. Ñîõðàíÿåò ñòåê âûçûâàþùåãî êîäà è óñòàíàâëèâàåò ñâîé ñòåê:
ss:sp = 0:(7C00-10), bp=7C00: ïàðà ss:bp ïðè ðàáîòå ñ îñòàëüíûì
êîäîì äîëæíà óêàçûâàòü íà 0:7C00, à -10 áåð¸òñÿ îò òîãî, ÷òî
èíèöèàëèçèðóþùèé êîä áóòñåêòîðà óæå ïîìåñòèë â ñòåê 10 áàéò ïàðàìåòðîâ,
è îíè äîëæíû ñîõðàíÿòüñÿ â íåèçìåííîñòè. (Çíà÷åíèå [ebp-14],
"òåêóùèé ñåêòîð, íàõîäÿùèéñÿ â êýøå FAT", íå èñïîëüçóåòñÿ ïîñëå
èíèöèàëèçàöèè êýøèðîâàíèÿ â kordldr.f32.)
2. Ðàçáèðàåò ïåðåäàííûå ïàðàìåòðû è âûçûâàåò íóæíóþ èç âñïîìîãàòåëüíûõ
ïðîöåäóð (çàãðóçêè ôàéëà ëèáî ïðîäîëæåíèÿ çàãðóçêè ôàéëà).
3. Âîññòàíàâëèâàåò ñòåê âûçûâàþùåãî êîäà è âîçâðàùàåò óïðàâëåíèå.
 
Âñïîìîãàòåëüíûå ïðîöåäóðû kordldr.f32.
Ïðîöåäóðà ïîëó÷åíèÿ ñëåäóþùåãî êëàñòåðà â FAT (get_next_cluster):
1. Âû÷èñëÿåò íîìåð ñåêòîðà â FAT, â êîòîðîì íàõîäèòñÿ çàïðîøåííûé ýëåìåíò.
(Â ñåêòîðå 0x200 áàéò, êàæäûé âõîä çàíèìàåò 4 áàéòà.)
2. Ïðîâåðÿåò, åñòü ëè ñåêòîð â êýøå. Åñëè åñòü, ïðîïóñêàåò øàãè 3 è 4.
3. Åñëè íåò, òî â êýø íóæíî âñòàâèòü íîâûé ýëåìåíò. Åñëè êýø åù¸ íå çàïîëíåí,
âûäåëÿåò î÷åðåäíîé ýëåìåíò â êîíöå êýøà. Åñëè çàïîëíåí, óäàëÿåò
ñàìûé ñòàðûé ýëåìåíò (òîò, ê êîòîðîìó äîëüøå âñåãî íå áûëî îáðàùåíèé);
äëÿ òîãî, ÷òîáû îòñëåæèâàòü ïîðÿäîê ýëåìåíòîâ ïî âðåìåíè ïîñëåäíåãî
îáðàùåíèÿ, âñå (âûäåëåííûå) ýëåìåíòû êýøà ñâÿçàíû â äâóñâÿçíûé ñïèñîê,
â êîòîðîì ïåðâûì ýëåìåíòîì ÿâëÿåòñÿ ñàìûé ñòàðûé, à ññûëêè âïåð¸ä
óêàçûâàþò íà ñëåäóþùèé ïî âðåìåíè ïîñëåäíåãî îáðàùåíèÿ.
4. ×èòàåò ñîîòâåòñòâóþùèé ñåêòîð FAT ñ äèñêà.
5. Êîððåêòèðóåò ñïèñîê: òåêóùèé îáðàáàòûâàåìûé ýëåìåíò óäàëÿåòñÿ ñ òîé ïîçèöèè,
ãäå îí íàõîäèòñÿ, è äîáàâëÿåòñÿ â êîíåö. ( ñëó÷àå ñî ñâåæåäîáàâëåííûìè
â êýø ýëåìåíòàìè óäàëåíèÿ íå äåëàåòñÿ, ïîñêîëüêó èõ â ñïèñêå åù¸ íåò.)
6. Ñ÷èòûâàåò íóæíûé âõîä â FAT, ñáðàñûâàÿ ñòàðøèå 4 áèòà.
7. Ñðàâíèâàåò ïðî÷èòàííîå çíà÷åíèå ñ ïðåäåëîì: åñëè îíî ñòðîãî ìåíüøå
0x0FFFFFF7, òî îíî çàäà¸ò íîìåð ñëåäóþùåãî êëàñòåðà â öåïî÷êå;
â ïðîòèâíîì ñëó÷àå öåïî÷êà çàêîí÷èëàñü.
 
Ïðîöåäóðà çàãðóçêè ôàéëà (load_file):
1. Òåêóùàÿ ðàññìàòðèâàåìàÿ ïàïêà - êîðíåâàÿ. Â öèêëå âûïîëíÿåò øàãè 2-4.
2. Êîíâåðòèðóåò èìÿ òåêóùåãî ðàññìàòðèâàåìîãî êîìïîíåíòà èìåíè (êîìïîíåíòû
ðàçäåëÿþòñÿ ñèìâîëîì '/') â FAT-ôîðìàò 8+3. Åñëè ýòî íåâîçìîæíî
(áîëüøå 8 ñèìâîëîâ â èìåíè, áîëüøå 3 ñèìâîëîâ â ðàñøèðåíèè èëè
áîëüøå îäíîé òî÷êè), âîçâðàùàåòñÿ ñ îøèáêîé.
3. Èùåò ýëåìåíò ñ òàêèì èìåíåì â òåêóùåé ðàññìàòðèâàåìîé ïàïêå.
à) Ïðîâåðÿåò, åñòü ëè òàêàÿ ïàïêà â êýøå ïàïîê. (Èäåíòèôèêàöèÿ ïàïîê
îñóùåñòâëÿåòñÿ ïî íîìåðó íà÷àëüíîãî êëàñòåðà.) Åñëè òàêîé ïàïêè åù¸
íåò, äîáàâëÿåò å¸ â êýø; åñëè òîò ïåðåïîëíÿåòñÿ, âûêèäûâàåò ïàïêó,
ê êîòîðîé äîëüøå âñåãî íå áûëî îáðàùåíèé. (Äëÿ êàæäîãî ýëåìåíòà êýøà
õðàíèòñÿ ìåòêà îò 0 äî (ðàçìåð êýøà)-1, îïðåäåëÿþùàÿ åãî íîìåð ïðè
ñîðòèðîâêå ïî äàâíîñòè ïîñëåäíåãî îáðàùåíèÿ. Ïðè îáðàùåíèè ê êàêîìó-òî
ýëåìåíòó åãî ìåòêà ñòàíîâèòñÿ íóëåâîé, à òå ìåòêè, êîòîðûå ìåíüøå
ñòàðîãî çíà÷åíèÿ, óâåëè÷èâàþòñÿ íà åäèíèöó.)
á) Ïðîñìàòðèâàåò â ïîèñêàõ çàïðîøåííîãî èìåíè âñå ýëåìåíòû èç êýøà,
èñïîëüçóÿ ïðîöåäóðó èç áóòñåêòîðà. Åñëè îáíàðóæèâàåò èñêîìûé ýëåìåíò,
ïåðåõîäèò ê øàãó 4. Åñëè îáíàðóæèâàåò êîíåö ïàïêè, âîçâðàùàåòñÿ èç
ïðîöåäóðû ñ îøèáêîé.
â)  öèêëå ñ÷èòûâàåò ïàïêó ïîñåêòîðíî. Ïðè ýòîì ïðîïóñêàåò íà÷àëüíûå
ñåêòîðû, êîòîðûå óæå íàõîäÿòñÿ â êýøå è óæå áûëè ïðîñìîòðåíû. Êàæäûé
ïðî÷èòàííûé ñåêòîð êîïèðóåò â êýø, åñëè òàì åù¸ îñòà¸òñÿ ìåñòî,
è ïðîñìàòðèâàåò â í¸ì âñå ýëåìåíòû. Ðàáîòàåò, ïîêà íå ñëó÷èòñÿ îäíî èç
òð¸õ ñîáûòèé: íàéäåí èñêîìûé ýëåìåíò; êîí÷èëèñü êëàñòåðû (ñóäÿ ïî
öåïî÷êå êëàñòåðîâ â FAT); î÷åðåäíîé ýëåìåíò ïàïêè ñèãíàëèçèðóåò î êîíöå
(ïåðâûé áàéò íóëåâîé).  äâóõ ïîñëåäíèõ ñëó÷àÿõ âîçâðàùàåòñÿ ñ îøèáêîé.
4. Ïðîâåðÿåò òèï íàéäåííîãî ýëåìåíòà (ôàéë/ïàïêà): ïîñëåäíèé ýëåìåíò â
çàïðîøåííîì èìåíè äîëæåí áûòü ôàéëîì, âñå ïðîìåæóòî÷íûå - ïàïêàìè.
Åñëè òåêóùèé êîìïîíåíò èìåíè - ïðîìåæóòî÷íûé, ïðîäâèãàåò òåêóùóþ
ðàññìàòðèâàåìóþ ïàïêó è âîçâðàùàåòñÿ ê ïóíêòó 2.
5. Ïðîõîäèò ïî öåïî÷êå êëàñòåðîâ â FAT è ñ÷èòûâàåò âñå êëàñòåðû â óêàçàííûé
ïðè âûçîâå áóôåð ïîñëåäîâàòåëüíûìè âûçîâàìè ôóíêöèè áóòñåêòîðà;
ïðè ýòîì åñëè íåñêîëüêî êëàñòåðîâ ôàéëà ðàñïîëîæåíû íà äèñêå
ïîñëåäîâàòåëüíî, òî èõ ÷òåíèå îáúåäèíÿåòñÿ â îäíó îïåðàöèþ.
Ñëåäèò çà òåì, ÷òîáû íå ïðåâûñèòü óêàçàííûé ïðè âûçîâå ïðîöåäóðû
ëèìèò ÷èñëà ñåêòîðîâ äëÿ ÷òåíèÿ.
 
Ïðîöåäóðà ïðîäîëæåíèÿ çàãðóçêè ôàéëà (continue_load_file): âñòðîåíà
âíóòðü øàãà 5 load_file; çàãðóæàåò â ðåãèñòðû íóæíûå çíà÷åíèÿ (ðàíåå
ñîõðàí¸ííûå èç load_file) è ïðîäîëæàåò øàã 5.
/kernel/branches/Kolibri-acpi/bootloader/extended_primary_loader/fat32/build.bat
0,0 → 1,3
@fasm -m 65535 bootsect.asm bootsect.bin
@fasm -m 65535 kordldr.f32.asm kordldr.f32
@pause
/kernel/branches/Kolibri-acpi/bootloader/extended_primary_loader/fat32/kordldr.f32.asm
0,0 → 1,673
; 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 FAT32 bootsector loads first cluster of this file to 0:7E00 and transfers control to here
; ss:bp = 0:7C00
; ds = 0
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 ?
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 ?
filesize:
dw ? ; BPB_FSInfo
dw ? ; BPB_BkBootSec
rb 12 ; BPB_Reserved
BS_DrvNum db ?
db ? ; BS_Reserved1
db ? ; BS_BootSig
dd ? ; BS_VolID
; rb 11 ; BS_VolLab
; rb 5 ; BS_FilSysType, first 5 bytes
read_sectors32 dw ?
read_sectors2 dw ?
err_ dw ?
noloader dw ?
cachelimit dw ?
fatcachehead rw 2
fatcacheend dw ?
rb 3 ; BS_FilSysType, last 3 bytes
curseg dw ?
num_sectors dd ?
cur_cluster dd ?
next_cluster dd ?
flags dw ?
cur_delta dd ?
end virtual
 
; procedures from boot sector
; LBA version
lba_read_sectors2 = 7CD6h
lba_err = 7CAAh
lba_noloader = 7CA7h ; = lba_err - 3
; CHS version
chs_read_sectors2 = 7CD2h
chs_err = 7CA6h
chs_noloader = 7CA3h ; = chs_err - 3
 
push eax cx ; save our position on disk
; determine version of bootsector (LBA vs CHS)
mov [read_sectors2], chs_read_sectors2
mov bx, chs_err
mov [err_], bx
; mov [noloader], chs_noloader
cmp byte [bx], 0xE8 ; [chs_err] = 0xE8 for CHS version, 0x14 for LBA version
jz @f
add [read_sectors2], lba_read_sectors2 - chs_read_sectors2
add [err_], lba_err - chs_err
; mov [noloader], lba_noloader
@@:
xor bx, bx
; determine size of cache for folders
int 12h ; ax = size of available base memory in Kb
sub ax, 92000h / 1024
jae @f
nomem:
mov si, nomem_str
jmp [err_]
@@:
shr ax, 3
mov [cachelimit], ax ; size of cache - 1
mov es, bx
; no folders in cache yet
mov di, foldcache_clus
mov cx, 8*4/2 + 1
xor ax, ax
rep stosw
; bootsector code caches one FAT sector, [bp-14], in 6000:0000
; initialize our (more advanced) FAT caching from this
mov di, 8400h
mov cx, di
lea si, [fatcachehead]
mov [si], si ; no sectors in cache:
mov [si+2], si ; 'prev' & 'next' links point to self
mov [fatcacheend], di ; first free item = 8400h
stosw ; 'next cached sector' link
stosw ; 'prev cached sector' link
mov eax, [bp-14]
stosd ; first sector number in cache
test eax, eax
js @f
mov [si], cx ; 'first cached sector' link = 8400h
mov [si+2], cx ; 'next cached sector' link = 8400h
mov [fatcacheend], di ; first free item = 8406h
@@:
; if cluster = sector, we need to read second part of our file
; (bootsector loads only first cluster of kordldr.f32)
pop cx eax ; restore our position on disk
cmp cx, 1
ja kordldr_full
sub eax, [bp-10]
inc eax
inc eax ; eax = first cluster of kordldr.f32
call get_next_cluster
jc @f
; jmp [noloader]
mov ax, [err_]
sub ax, 3
jmp ax
@@:
dec eax
dec eax
push 0x800
pop es
call [read_sectors2]
kordldr_full:
; bootsector code has read some data of root directory to 8000:0000
; initialize our folder caching from this
mov eax, [BPB_RootClus]
mov [foldcache_clus], eax
mov cx, [curseg]
mov ax, 8000h
sub cx, ax ; cx = size of data read in paragraphs (0x10 bytes)
shr cx, 1 ; cx = size of folder data read in entries (0x20 bytes)
mov [foldcache_size], cx
shl cx, 4
push ds
mov ds, ax
push 0x9000
pop es
xor si, si
xor di, di
rep movsw
pop ds
; ...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
; push hooked_err / ret
mov dword [bx], 0x68 + (hooked_err shl 8) + (0xC3 shl 24)
; set registers for secondary loader
mov ah, [bp-2] ; drive id
mov al, 'f'
btr ax, 15
jnc @f
mov al, 'h'
@@:
mov bx, '32'
mov si, callback
jmp far [si+secondary_loader_info-callback]
 
nomem_str db 'No memory',0
 
cluster2sector:
sub eax, 2
clustersz2sectorsz:
movzx ecx, [BPB_SecsPerClus]
mul ecx
ret
 
get_next_cluster:
; in: eax = cluster
; out: if there is next cluster: CF=1, eax = next cluster
; out: if there is no next cluster: CF=0
push di bx
push ds es
push ss
pop ds
push ss
pop es
push ax
shr eax, 7
; eax = FAT sector number; look in cache
mov di, 8400h
.cache_lookup:
cmp di, [fatcacheend]
jae .not_in_cache
scasd
scasd
jnz .cache_lookup
.in_cache:
sub di, 8
; delete this sector from the list
push si
mov si, [di]
mov bx, [di+2]
mov [si+2], bx
mov [bx], si
pop si
jmp @f
.not_in_cache:
; cache miss
; cache is full?
mov di, [fatcacheend]
cmp di, 8C00h
jnz .cache_not_full
; yes, delete the oldest entry
mov di, [fatcachehead]
mov bx, [di]
mov [fatcachehead], bx
push word [di+2]
pop word [bx+2]
jmp .cache_append
.cache_not_full:
; no, allocate new sector
add [fatcacheend], 8
.cache_append:
; read FAT
mov [di+4], eax
pushad
lea cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))] ; +0x10000 - for FASM
shl cx, 9-4-3
mov es, cx
xor bx, bx
mov cx, 1
add eax, [bp-6] ; FAT start
sub eax, [bp-10]
call [read_sectors2]
popad
@@:
; add new sector to the end of list
mov bx, di
xchg bx, [fatcachehead+2]
push word [bx]
pop word [di]
mov [bx], di
mov [di+2], bx
; get requested item
lea ax, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))]
pop di
and di, 0x7F
shl di, 2
shl ax, 9-4-3
mov ds, ax
and byte [di+3], 0x0F
mov eax, [di]
pop es ds
pop bx di
;and eax, 0x0FFFFFFF
cmp eax, 0x0FFFFFF7
ret
 
if $ > 0x8000
error 'get_next_cluster must fit in first sector of kordldr.f32!'
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)
mov eax, [BPB_RootClus] ; start from root directory
or dword [filesize], -1 ; 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
filename equ bp
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 ; eax = cluster of directory
; high word of eax is preserved by operations above
push ds
push si
; read a folder sector-by-sector and scan
; first, try to use the cache
push ss
pop ds
mov di, foldcache_mark
xor bx, bx
mov cx, [cachelimit]
@@:
lea si, [di+bx]
mov edx, dword [foldcache_clus+si-foldcache_mark+bx]
cmp edx, eax
jz cacheok
test edx, edx
jz cacheadd ; the cache has place for new entry
inc bx
inc bx
dec cx
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 bx, -2
mov dx, [cachelimit]
@@:
inc bx
inc bx
cmp word [di+bx], dx ; marks have values 0 through [cachelimit]
jnz @b
lea si, [di+bx]
cacheadd:
or word [di+bx], 0xFFFF ; very big value, it will be changed soon
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet
mov dword [foldcache_clus+si-foldcache_mark+bx], eax
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
;mov dx, bx
;shl dx, 8 ; dx = (position in cache)*0x2000/0x10
;add dx, 0x9000
lea dx, [bx + 0x90]
xchg dl, dh
mov ds, dx
mov si, filename ; ss:si -> filename in FAT style
call scan_for_filename
jz lookup_done
; 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
push eax
call cluster2sector
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
push eax
call [read_sectors2]
pop eax
; copy data to the cache...
pop ds
pop di es
cmp di, 0x2000 ; ...if there is free space, of course
jae @f
pusha
mov cx, 0x100
xor si, si
rep movsw
mov di, es
shr di, 8
add [ss:foldcache_size+di-0x90], 0x10 ; 0x10 new entries in the cache
popa
@@:
push es
mov cl, 0x10 ; ch=0 at this point
call scan_for_filename
pop es
pop cx
jz lookup_done_pop
folder_skip_sector:
inc eax
loop folder_next_sector
pop eax ; eax = current cluster
call get_next_cluster
jc folder_next_cluster
stc
push eax
lookup_done_pop:
pop eax
lookup_done:
pop si
; CF=1 <=> failed
jnc found
pop ds
notfound:
pop di
notfound2:
mov bx, 2 ; file not found
mov ax, 0xFFFF
mov dx, ax ; invalid file size
ret
notfound_pop:
pop ax
jmp notfound
found:
mov eax, [di+20-2]
mov edx, [di+28]
mov ax, [di+26] ; get cluster
test byte [di+11], 10h ; directory?
pop ds
pop di
jz regular_file
cmp byte [si-1], 0
jz notfound2 ; don't read directories as regular files
; ok, we have found a directory and the caller requested a file into it
jmp parse_dir_loop ; restart with new cluster in ax
regular_file:
cmp byte [si-1], 0
jnz notfound2 ; file does not contain another files
; ok, we have found a regular file and the caller requested it
; save file size
mov [filesize], edx
mov si, [di+4] ; [ds:di+4] = limit in 4K blocks
shl si, 3
push si
les bx, [di] ; es:bx -> buffer
clusloop:
; eax = first cluster, top of stack contains limit in sectors
mov esi, eax ; remember current cluster
xor ecx, ecx ; ecx will contain number of consecutive clusters
mov [cur_delta], ecx
mov edi, eax
clusfind:
inc edi
inc ecx
call get_next_cluster
jnc clusread
cmp eax, edi
jz clusfind
stc
clusread:
pop di ; limit in sectors
movzx edi, di
push eax ; save next cluster
pushf ; save flags
; read cx clusters, starting from si
; calculate number of sectors
xchg eax, ecx
call clustersz2sectorsz
mov [num_sectors], eax
jmp @f
continue_load_file:
les bx, [di] ; es:bx -> buffer
movzx edi, word [di+4] ; di = limit in 4K blocks
shl di, 3 ; now di = limit in sectors
mov eax, [num_sectors]
mov esi, [cur_cluster]
push [next_cluster]
push [flags]
test eax, eax
jz nextclus
@@:
; eax = number of sectors; compare with limit
cmp eax, edi
seta dl
push dx ; limit was exceeded?
jbe @f
mov eax, edi
@@:
sub di, ax ; calculate new limit
sub [num_sectors], eax
mov [cur_cluster], esi
; calculate starting sector
push ax
xchg eax, esi
call cluster2sector
pop cx
add eax, [cur_delta]
add [cur_delta], ecx
; read
call [read_sectors2]
pop dx
; next cluster?
nextclus:
popf
pop eax
mov [next_cluster], eax
pushf
pop [flags]
jnc @f ; no next cluster => return
mov dl, 1
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-14-2 ; restore stack
mov dl, 3 ; return: read error
@@:
mov bl, dl
mov bh, 0
mov ax, [filesize]
mov dx, [filesize+2]
ret
 
scan_for_filename:
; in: ss:si -> 11-bytes FAT name
; in: ds:0 -> part of directory data
; in: cx = number of entries
; in: bh = 0
; 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
push ds
pop es
xor di, di
push cx
jcxz snoent
sloop:
cmp byte [di], bh
jz snotfound
test byte [di+11], 8 ; volume label?
jnz scont ; ignore volume labels
pusha
mov cx, 11
repz cmps byte [ss:si], byte [es:di]
popa
jz sdone
scont:
add di, 0x20
loop sloop
snoent:
inc cx ; clear ZF flag
snotfound:
stc
sdone:
pop cx
lrdret:
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-10
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 'kernel.mnt',0
aKernelNotFound db 'Fatal error: cannot load the kernel',0
 
;if $ > 0x8200
;error 'total size of kordldr.f32 must not exceed 1024 bytes!'
;end if
 
;foldcache_clus dd 0,0,0,0,0,0,0,0 ; start with no folders in cache
;foldcache_mark dw 0
; rw 7
;foldcache_size rw 8
foldcache_clus rd 8
foldcache_mark rw 8
foldcache_size rw 8
/kernel/branches/Kolibri-acpi/bootloader/extended_primary_loader/fat32/.
Property changes:
Added: bugtraq:number
+true
\ No newline at end of property
Added: tsvn:logminsize
+5
\ No newline at end of property