/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 |