/kernel/trunk/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/trunk/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/trunk/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/trunk/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/trunk/bootloader/extended_primary_loader/fat32 |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/kernel/trunk/bootloader/extended_primary_loader/after_win/kordldr.win.asm |
---|
0,0 → 1,921 |
; 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. |
;***************************************************************************** |
; KordOS bootloader, based on mtldr, KolibriOS bootloader, by diamond |
; It is used when main bootloader is Windows loader. |
; this code is loaded: |
; NT/2k/XP: by ntldr to 0D00:0000 |
; 9x: by io.sys from config.sys to xxxx:0100 |
; Vista: by bootmgr to 0000:7C00 |
format binary |
use16 |
; in any case, we relocate this code to 0000:0600 |
org 0x600 |
; entry point for 9x and Vista booting |
call @f |
db 'NTFS' |
@@: |
pop si |
sub si, 3 |
cmp si, 100h |
jnz boot_vista |
mov si, load_question + 100h - 600h |
call out_string |
; mov si, answer + 100h - 0600h ; already is |
xxy: mov ah, 0 |
int 16h |
or al, 20h |
mov [si], al |
cmp al, 'y' |
jz xxz |
cmp al, 'n' |
jnz xxy |
; continue load Windows |
; call out_string |
; ret |
out_string: |
push bx |
@@: |
lodsb |
test al, al |
jz @f |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp @b |
@@: |
pop bx |
ret |
xxz: |
; boot KordOS |
call out_string |
; 9x bootloader has already hooked some interrupts; to correctly remove all DOS handlers, |
; issue int 19h (reboot interrupt) and trace its DOS handler until original BIOS handler is reached |
xor di, di |
mov ds, di |
mov word [di+4], new01handler + 100h - 600h |
mov [di+6], cs |
pushf |
pop ax |
or ah, 1 |
push ax |
popf |
; we cannot issue INT 19h directly, because INT command clears TF |
; int 19h ; don't issue it directly, because INT command clears TF |
; so instead we use direct call |
; pushf ; there will be no IRET |
call far [di + 19h*4] |
xxt: |
xor di, di |
mov ds, di |
cmp word [di + 8*4+2], 0F000h |
jz @f |
les bx, [di + 8*4] |
mov eax, [es:bx+1] |
mov [di + 8*4], eax |
@@: |
mov si, 100h |
boot_vista: |
; relocate cs:si -> 0000:0600 |
push cs |
pop ds |
xor ax, ax |
mov es, ax |
mov di, 0x600 |
mov cx, 2000h/2 |
rep movsw |
jmp 0:real_entry |
load_question db 'Load KordOS? [y/n]: ',0 |
answer db ? |
db 13,10,0 |
new01handler: |
; [sp]=ip, [sp+2]=cs, [sp+4]=flags |
push bp |
mov bp, sp |
push ds |
lds bp, [bp+2] |
cmp word [ds:bp], 19cdh |
jz xxt |
pop ds |
pop bp |
iret |
; read from hard disk |
; in: eax = absolute sector |
; cx = number of sectors |
; es:bx -> buffer |
; out: CF=1 if error |
read: |
pushad |
add eax, [bp + partition_start - dat] |
cmp [bp + use_lba - dat], 0 |
jz .chs |
; LBA read |
push ds |
.lbado: |
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 + boot_drive - dat] |
mov ah, 42h |
int 13h |
jc .disk_error_lba |
add sp, 10h ; restore stack |
; 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 .lbado |
pop ds |
popad |
ret |
.disk_error_lba: |
add sp, 14h |
pop ds |
popad |
stc |
ret |
.chs: |
pusha |
pop edi ; loword(edi) = di, hiword(edi) = si |
push bx |
; eax / (SectorsPerTrack) -> eax, remainder bx |
movzx esi, [bp + sectors - dat] |
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 + heads - dat] |
; 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 + boot_drive - dat] |
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 |
add sp, 12 |
popad |
stc |
ret |
@@: |
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 .chs |
popad |
ret |
disk_error2 db 'Fatal: cannot read partitions info: ' |
disk_error_msg db 'disk read error',0 |
disk_params_msg db 'Fatal: cannot get drive parameters',0 |
start_msg db 2,' KordOS bootloader',13,10,0 |
part_msg db 'looking at partition ' |
part_char db '0' ; will be incremented before writing message |
db ' ... ',0 |
errfs_msg db 'unknown filesystem',13,10,0 |
fatxx_msg db 'FATxx' |
newline db 13,10,0 |
ntfs_msg db 'NTFS',13,10,0 |
error_msg db 'Error' |
colon db ': ',0 |
root_string db '\',0 |
nomem_msg db 'No memory',0 |
filesys_string db '(filesystem)',0 |
directory_string db 'is a directory',0 |
notdir_string db 'not a directory',0 |
; entry point for NT/2k/XP booting |
; ntldr loads our code to 0D00:0000 and jumps to 0D00:0256 |
repeat 600h + 256h - $ |
db 1 ; any data can be here; 1 in ASCII is a nice face :) |
end repeat |
; cs=es=0D00, ds=07C0, ss=0 |
; esi=edi=ebp=0, esp=7C00 |
xor si, si |
jmp boot_vista |
real_entry: |
; ax = 0 |
mov ds, ax |
mov es, ax |
; our stack is 4 Kb: memory range 2000-3000 |
mov ss, ax |
mov sp, 3000h |
mov bp, dat |
sti ; just for case |
; say hi to user |
mov si, start_msg |
call out_string |
; we are booting from hard disk identified by [boot_drive] |
mov dl, [bp + boot_drive - dat] |
; is LBA supported? |
mov [bp + use_lba - dat], 0 |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
jc .no_lba |
cmp bx, 0AA55h |
jnz .no_lba |
test cl, 1 |
jz .no_lba |
inc [bp + use_lba - dat] |
jmp disk_params_ok |
.no_lba: |
; get drive geometry |
mov ah, 8 |
mov dl, [bp + boot_drive - dat] |
int 13h |
jnc @f |
mov si, disk_params_msg |
call out_string |
jmp $ |
@@: |
movzx ax, dh |
inc ax |
mov [bp + heads - dat], ax |
and cx, 3Fh |
mov [bp + sectors - dat], cx |
disk_params_ok: |
; determine size of cache for folders |
int 12h ; ax = size of available base memory in Kb |
sub ax, 94000h / 1024 |
jc nomem |
shr ax, 3 |
mov [bp + cachelimit - dat], ax ; size of cache - 1 |
; scan all partitions |
new_partition_ex: |
xor eax, eax ; read first sector of current disk area |
mov [bp + extended_part_cur - dat], eax ; no extended partition yet |
mov [bp + cur_partition_ofs - dat], 31BEh ; start from first partition |
push es |
mov cx, 1 |
mov bx, 3000h |
call read |
pop es |
jnc new_partition |
mov si, disk_error2 |
call out_string |
jmp $ |
new_partition: |
mov bx, [bp + cur_partition_ofs - dat] |
mov al, [bx+4] ; partition type |
test al, al |
jz next_partition |
cmp al, 5 |
jz @f |
cmp al, 0xF |
jnz not_extended |
@@: |
; extended partition |
mov eax, [bx+8] ; partition start |
add eax, [bp + extended_part_start - dat] |
mov [bp + extended_part_cur - dat], eax |
next_partition: |
add [bp + cur_partition_ofs - dat], 10h |
cmp [bp + cur_partition_ofs - dat], 31FEh |
jb new_partition |
mov eax, [bp + extended_part_cur - dat] |
test eax, eax |
jz partitions_done |
cmp [bp + extended_part_start - dat], 0 |
jnz @f |
mov [bp + extended_part_start - dat], eax |
@@: |
mov [bp + extended_parent - dat], eax |
mov [bp + partition_start - dat], eax |
jmp new_partition_ex |
partitions_done: |
mov si, total_kaput |
call out_string |
jmp $ |
not_extended: |
mov eax, [bx+8] |
add eax, [bp + extended_parent - dat] |
mov [bp + partition_start - dat], eax |
; try to load from current partition |
; inform user |
mov si, part_msg |
inc [si + part_char - part_msg] |
call out_string |
; read bootsector |
xor eax, eax |
mov [bp + cur_obj - dat], filesys_string |
push es |
mov cx, 1 |
mov bx, 3200h |
call read |
pop es |
mov si, disk_error_msg |
jc find_error_si |
movzx si, byte [bx+13] |
mov word [bp + sect_per_clust - dat], si |
test si, si |
jz unknown_fs |
lea ax, [si-1] |
test si, ax |
jnz unknown_fs |
; determine file system |
; Number of bytes per sector == 0x200 (this loader assumes that physical sector size is 200h) |
cmp word [bx+11], 0x200 |
jnz unknown_fs |
; is it NTFS? |
cmp dword [bx+3], 'NTFS' |
jnz not_ntfs |
cmp byte [bx+16], bl |
jz ntfs |
not_ntfs: |
; is it FAT? FAT12/FAT16/FAT32? |
; get count of sectors to dword in cx:si |
mov si, [bx+19] |
xor cx, cx |
test si, si |
jnz @f |
mov si, [bx+32] |
mov cx, [bx+34] |
@@: |
xor eax, eax |
; subtract size of system area |
sub si, [bx+14] ; BPB_ResvdSecCnt |
sbb cx, ax |
mov ax, [bx+17] ; BPB_RootEntCnt |
add ax, 0xF |
rcr ax, 1 |
shr ax, 3 |
sub si, ax |
sbb cx, 0 |
push cx |
push si |
mov ax, word [bx+22] |
test ax, ax |
jnz @f |
mov eax, [bx+36] |
@@: |
movzx ecx, byte [bx+16] |
imul ecx, eax |
pop eax |
sub eax, ecx |
; now eax = count of sectors in the data region |
xor edx, edx |
div [bp + sect_per_clust - dat] |
; now eax = count of clusters in the data region |
mov si, fatxx_msg |
cmp eax, 0xFFF5 |
jae test_fat32 |
; test magic value in FAT bootsector - FAT12/16 bootsector has it at the offset +38 |
cmp byte [bx+38], 0x29 |
jnz not_fat |
cmp ax, 0xFF5 |
jae fat16 |
fat12: |
mov [bp + get_next_cluster_ptr - dat], fat12_get_next_cluster |
mov di, cx ; BPB_NumFATs |
mov ax, '12' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
movzx ecx, word [bx+22] ; BPB_FATSz16 |
; FAT12: read entire FAT table (it is no more than 0x1000*3/2 = 0x1800 bytes) |
.fatloop: |
; if first copy is not readable, try to switch to other copies |
push 0x6000 |
pop es |
xor bx, bx |
movzx eax, word [0x320E] ; BPB_RsvdSecCnt |
push cx |
cmp cx, 12 |
jb @f |
mov cx, 12 |
@@: |
call read |
pop cx |
jnc fat1x_common |
add eax, ecx ; switch to next copy of FAT |
dec di |
jnz .fatloop |
mov si, disk_error_msg |
jmp find_error_si |
fat16: |
mov [bp + get_next_cluster_ptr - dat], fat16_get_next_cluster |
mov ax, '16' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
; FAT16: init FAT cache - no sectors loaded |
mov di, 0x3400 |
xor ax, ax |
mov cx, 0x100/2 |
rep stosw |
fat1x_common: |
mov bx, 0x3200 |
movzx eax, word [bx+22] ; BPB_FATSz16 |
xor esi, esi ; no root cluster |
jmp fat_common |
test_fat32: |
; FAT32 bootsector has it at the offset +66 |
cmp byte [bx+66], 0x29 |
jnz not_fat |
mov [bp + get_next_cluster_ptr - dat], fat32_get_next_cluster |
mov ax, '32' |
push ax ; save for secondary loader |
mov word [si+3], ax |
call out_string |
; FAT32 - init cache for FAT table: no sectors loaded |
lea si, [bp + cache1head - dat] |
mov [si], si ; no sectors in cache: |
mov [si+2], si ; 'prev' & 'next' links point to self |
mov [bp + cache1end - dat], 3400h ; first free item = 3400h |
mov [bp + cache1limit - dat], 3C00h |
mov eax, [bx+36] ; BPB_FATSz32 |
mov esi, [bx+44] ; BPB_RootClus |
jmp fat_common |
not_fat: |
unknown_fs: |
mov si, errfs_msg |
call out_string |
jmp next_partition |
fat_common: |
push ss |
pop es |
movzx edx, byte [bx+16] ; BPB_NumFATs |
mul edx |
mov [bp + root_start - dat], eax ; this is for FAT1x |
; eax = total size of all FAT tables, in sectors |
movzx ecx, word [bx+17] ; BPB_RootEntCnt |
add ecx, 0xF |
shr ecx, 4 |
add eax, ecx |
mov cx, word [bx+14] ; BPB_RsvdSecCnt |
add [bp + root_start - dat], ecx ; this is for FAT1x |
add eax, ecx |
; cluster 2 begins from sector eax |
movzx ebx, byte [bx+13] ; BPB_SecPerClus |
sub eax, ebx |
sub eax, ebx |
mov [bp + data_start - dat], eax |
; no clusters in folders cache |
mov di, foldcache_clus - 2 |
xor ax, ax |
mov cx, 7*8/2 + 1 |
rep stosw |
mov [bp + root_clus - dat], esi |
; load secondary loader |
mov [bp + load_file_ptr - dat], load_file_fat |
load_secondary: |
push 0x1000 |
pop es |
xor bx, bx |
mov si, kernel_name |
mov cx, 0x30000 / 0x200 |
call [bp + load_file_ptr - dat] |
; say error if needed |
mov si, error_too_big |
dec bx |
js @f |
jz find_error_si |
mov si, disk_error_msg |
jmp find_error_si |
@@: |
; fill loader information and jump to secondary loader |
mov al, 'h' ; boot device: hard drive |
mov ah, [bp + boot_drive - dat] |
sub ah, 80h ; boot device: identifier |
pop bx ; restore file system ID ('12'/'16'/'32'/'nt') |
mov si, callback |
jmp 1000h:0000h |
nomem: |
mov si, nomem_msg |
call out_string |
jmp $ |
ntfs: |
push 'nt' ; save for secondary loader |
mov si, ntfs_msg |
call out_string |
xor eax, eax |
mov [bp + data_start - dat], eax |
mov ecx, [bx+40h] ; frs_size |
cmp cl, al |
jg .1 |
neg cl |
inc ax |
shl eax, cl |
jmp .2 |
.1: |
mov eax, ecx |
shl eax, 9 |
.2: |
mov [bp + frs_size - dat], ax |
; standard value for frs_size is 0x400 bytes = 1 Kb, and it cannot be set different |
; (at least with standard tools) |
; we allow extra size, but no more than 0x1000 bytes = 4 Kb |
mov si, invalid_volume_msg |
cmp eax, 0x1000 |
ja find_error_si |
; must be multiple of sector size |
test ax, 0x1FF |
jnz find_error_si |
shr ax, 9 |
xchg cx, ax |
; initialize cache - no data loaded |
lea si, [bp + cache1head - dat] |
mov [si], si |
mov [si+2], si |
mov word [si+4], 3400h ; first free item = 3400h |
mov word [si+6], 3400h + 8*8 ; 8 items in this cache |
; read first MFT record - description of MFT itself |
mov [bp + cur_obj - dat], mft_string |
mov eax, [bx+30h] ; mft_cluster |
mul [bp + sect_per_clust - dat] |
push 0x8000 |
pop es |
xor bx, bx |
push es |
call read |
pop ds |
call restore_usa |
; scan for unnamed $DATA attribute |
mov [bp + freeattr - dat], 4000h |
mov ax, 80h |
call load_attr |
push ss |
pop ds |
mov si, nodata_string |
jc find_error_si |
; load secondary loader |
mov [bp + load_file_ptr - dat], load_file_ntfs |
jmp load_secondary |
find_error_si: |
push si |
find_error_sp: |
cmp [bp + in_callback - dat], 0 |
jnz error_in_callback |
push ss |
pop ds |
push ss |
pop es |
mov si, error_msg |
call out_string |
mov si, [bp + cur_obj - dat] |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jz @f |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp @b |
@@: |
mov si, colon |
call out_string |
pop si |
call out_string |
mov si, newline |
call out_string |
mov sp, 0x3000 |
jmp next_partition |
error_in_callback: |
; return status: file not found, except for read errors |
mov bx, 2 |
cmp si, disk_error_msg |
jnz @f |
inc bx |
@@: |
mov ax, 0xFFFF |
mov dx, ax |
mov sp, 3000h - 6 |
ret |
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, 3000h |
mov bp, dat |
mov [bp + in_callback - dat], 1 |
push dx |
push cx |
; set ds:si -> ASCIIZ name |
lea si, [di+6] |
; set cx = limit in sectors; 4Kb = 8 sectors |
movzx ecx, word [di+4] |
shl cx, 3 |
; set es:bx = pointer to buffer |
les bx, [di] |
; call our function |
stc ; unsupported function |
dec ax |
jz callback_readfile |
dec ax |
jnz callback_ret |
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 [bp + load_file_ptr - dat] |
callback_ret_succ: |
clc |
callback_ret: |
; restore caller's stack |
pop cx |
pop ss |
mov sp, cx |
; return to caller |
retf |
read_file_chunk.resident: |
; auxiliary label for read_file_chunk procedure |
mov di, bx |
lodsw |
read_file_chunk.resident.continue: |
mov dx, ax |
add dx, 0x1FF |
shr dx, 9 |
cmp dx, cx |
jbe @f |
mov ax, cx |
shl ax, 9 |
@@: |
xchg ax, cx |
rep movsb |
xchg ax, cx |
clc ; no disk error if no disk requests |
mov word [bp + num_sectors - dat], ax |
ret |
read_file_chunk: |
; in: ds:si -> file chunk |
; in: es:bx -> buffer for output |
; in: ecx = maximum number of sectors to read (high word must be 0) |
; out: CF=1 <=> disk read error |
lodsb |
mov [bp + cur_chunk_resident - dat], al |
test al, al |
jz .resident |
; normal case: load (non-resident) attribute from disk |
.read_block: |
lodsd |
xchg eax, edx |
test edx, edx |
jz .ret |
lodsd |
; eax = start cluster, edx = number of clusters, cx = limit in sectors |
imul eax, [bp + sect_per_clust - dat] |
add eax, [bp + data_start - dat] |
mov [bp + cur_cluster - dat], eax |
imul edx, [bp + sect_per_clust - dat] |
mov [bp + num_sectors - dat], edx |
and [bp + cur_delta - dat], 0 |
.nonresident.continue: |
cmp edx, ecx |
jb @f |
mov edx, ecx |
@@: |
test dx, dx |
jz .read_block |
add [bp + cur_delta - dat], edx |
sub [bp + num_sectors - dat], edx |
sub ecx, edx |
push cx |
mov cx, dx |
call read |
pop cx |
jc .ret |
test cx, cx |
jnz .read_block |
.ret: |
ret |
cache_lookup: |
; in: eax = value to look, si = pointer to cache structure |
; out: di->cache entry; CF=1 <=> the value was not found |
push ds bx |
push ss |
pop ds |
mov di, [si+2] |
.look: |
cmp di, si |
jz .not_in_cache |
cmp eax, [di+4] |
jz .in_cache |
mov di, [di+2] |
jmp .look |
.not_in_cache: |
; cache miss |
; cache is full? |
mov di, [si+4] |
cmp di, [si+6] |
jnz .cache_not_full |
; yes, delete the oldest entry |
mov di, [si] |
mov bx, [di] |
mov [si], bx |
push word [di+2] |
pop word [bx+2] |
jmp .cache_append |
.cache_not_full: |
; no, allocate new item |
add word [si+4], 8 |
.cache_append: |
mov [di+4], eax |
stc |
jmp @f |
.in_cache: |
; delete this sector from the list |
push si |
mov si, [di] |
mov bx, [di+2] |
mov [si+2], bx |
mov [bx], si |
pop si |
@@: |
; add new sector to the end of list |
mov bx, di |
xchg bx, [si+2] |
push word [bx] |
pop word [di] |
mov [bx], di |
mov [di+2], bx |
pop bx ds |
ret |
include 'fat.inc' |
include 'ntfs.inc' |
total_kaput db 13,10,'Fatal error: cannot load the secondary loader',0 |
error_too_big db 'file is too big',0 |
nodata_string db '$DATA ' |
error_not_found db 'not found',0 |
noindex_string db '$INDEX_ROOT not found',0 |
badname_msg db 'bad name for FAT',0 |
invalid_volume_msg db 'invalid volume',0 |
mft_string db '$MFT',0 |
fragmented_string db 'too fragmented file',0 |
invalid_read_request_string db 'cannot read attribute',0 |
kernel_name db 'kernel.mnt',0 |
align 4 |
dat: |
extended_part_start dd 0 ; start sector for main extended partition |
extended_part_cur dd ? ; start sector for current extended child |
extended_parent dd 0 ; start sector for current extended parent |
partition_start dd 0 ; start sector for current logical disk |
cur_partition_ofs dw ? ; offset in MBR data for current partition |
sect_per_clust dd 0 |
; change this variable if you want to boot from other physical drive |
boot_drive db 80h |
in_callback db 0 |
; uninitialized data |
use_lba db ? |
cur_chunk_resident db ? |
align 2 |
heads dw ? |
sectors dw ? |
cache1head rw 2 |
cache1end dw ? |
cache1limit dw ? |
data_start dd ? |
cachelimit dw ? |
load_file_ptr dw ? |
cur_obj dw ? |
missing_slash dw ? |
root_clus dd ? |
root_start dd ? |
get_next_cluster_ptr dw ? |
frs_size dw ? |
freeattr dw ? |
index_root dw ? |
index_alloc dw ? |
cur_index_seg dw ? |
cur_index_cache dw ? |
filesize dd ? |
filesize_sectors dd ? |
cur_cluster dd ? |
cur_delta dd ? |
num_sectors dd ? |
sectors_read dd ? |
cur_chunk_ptr dw ? |
rootcache_size dw ? ; must be immediately before foldcache_clus |
if $-dat >= 0x80 |
warning: unoptimal data displacement! |
end if |
foldcache_clus rd 7 |
foldcache_mark rw 7 |
foldcache_size rw 7 |
fat_filename rb 11 |
if $ > 2000h |
error: file is too big |
end if |
; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long |
repeat 0x2600 - $ |
db 2 ; any data can be here; 2 is another nice face in ASCII :) |
end repeat |
/kernel/trunk/bootloader/extended_primary_loader/after_win/build.bat |
---|
0,0 → 1,2 |
@fasm -m 65535 kordldr.win.asm kordldr.win |
@pause |
/kernel/trunk/bootloader/extended_primary_loader/after_win/fat.inc |
---|
0,0 → 1,509 |
; 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. |
;***************************************************************************** |
; in: ss:bp = 0:dat |
; in: es:bx = address to load file |
; in: ds:si -> ASCIIZ name |
; in: cx = limit in sectors |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file has been loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
load_file_fat: |
mov eax, [bp + root_clus - dat] |
mov [bp + cur_obj - dat], root_string |
push es |
push bx |
push cx |
.parse_dir_loop: |
; convert name to FAT name |
push [bp + cur_obj - dat] |
push ax |
mov [bp + cur_obj - dat], si |
push ss |
pop es |
; convert ASCIIZ filename to FAT name |
mov di, fat_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: |
mov si, badname_msg |
jmp find_error_si |
.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 bx, -2 |
mov cx, [bp + rootcache_size - dat] |
cmp [bp + root_clus - dat], eax |
jz .lookcache_root |
mov di, foldcache_mark |
xor bx, bx |
mov cx, [bp + cachelimit - dat] |
@@: |
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 |
js @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, [bp + cachelimit - dat] |
@@: |
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 |
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet |
lea si, [di+bx] |
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, [bp + cachelimit - dat] |
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 |
.lookcache_root: |
; bx = (position in cache)*2 for non-root folders; bx = -2 for root folder |
;mov dx, bx |
;shl dx, 8 |
;add dx, 0x9200 |
lea dx, [bx + 0x92] |
xchg dl, dh |
mov ds, dx |
mov si, fat_filename ; ss:si -> filename in FAT style |
call fat_scan_for_filename |
jz .lookup_done |
; cache miss, read folder data from disk |
; we are reading parent directory, it can result in disk read errors; restore [cur_obj] |
mov di, sp |
mov bx, [bp + cur_obj - dat] |
xchg bx, [ss:di+4] |
mov [bp + cur_obj - dat], bx |
mov bx, cx |
add bx, 0xF |
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 |
movzx ecx, byte [ss:0x320D] ; BPB_SecPerClus |
push eax |
; FAT12/16 root - special handling |
test eax, eax |
jnz .folder_notroot |
mov cx, [ss:0x3211] ; BPB_RootEntCnt |
mov dx, cx |
add cx, 0xF |
rcr cx, 1 |
shr cx, 3 |
mov eax, [bp + root_start - dat] |
jmp .folder_next_sector |
.folder_notroot: |
mul ecx |
add eax, [bp + data_start - dat] |
.folder_next_sector: |
sub dx, 0x10 |
; 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 |
jc ..found_disk_error |
; 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 |
cmp di, 0x90 |
jz .update_rootcache_size |
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache |
jmp .updated_cachesize |
.update_rootcache_size: |
mov cl, 0x10 |
cmp cx, dx |
jb @f |
mov cx, dx |
@@: |
add [bp + rootcache_size - dat], cx |
.updated_cachesize: |
popa |
@@: |
push es |
mov cl, 0x10 ; ch=0 at this point |
cmp cx, dx |
jb @f |
mov cx, dx |
@@: |
call fat_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 |
test eax, eax |
jz @f |
call [bp + get_next_cluster_ptr - dat] |
jc .folder_next_cluster |
@@: |
stc |
push eax |
.lookup_done_pop: |
pop eax |
.lookup_done: |
pop si |
; CF=1 <=> failed |
jnc .found |
pop ds |
pop [bp + cur_obj - dat] |
mov si, error_not_found |
jmp find_error_si |
.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 [bp + cur_obj - dat] ; forget old [cur_obj] |
jz .regular_file |
cmp byte [si-1], 0 |
jnz .parse_dir_loop |
..directory_error: |
mov si, directory_string |
jmp find_error_si |
.regular_file: |
cmp byte [si-1], 0 |
jz @f |
..notdir_error: |
mov si, notdir_string |
jmp find_error_si |
@@: |
; ok, we have found a regular file and the caller requested it |
; parse FAT chunk |
push ss |
pop es |
push ss |
pop ds |
mov di, 0x4005 |
mov byte [di-5], 1 ; non-resident attribute |
mov dword [di-4], 1 |
stosd |
pop cx |
push cx |
.parsefat: |
call [bp + get_next_cluster_ptr - dat] |
jnc .done |
mov esi, [di-8] |
add esi, [di-4] |
cmp eax, esi |
jz .contc |
mov dword [di], 1 |
scasd |
stosd |
jmp @f |
.contc: |
inc dword [di-8] |
@@: |
sub cl, [0x320D] |
sbb ch, 0 |
ja .parsefat |
.done: |
xor eax, eax |
stosd |
mov si, 0x4000 |
load_file_common_end: |
xor ecx, ecx |
pop cx |
pop bx |
pop es |
mov [bp + filesize - dat], edx |
mov [bp + sectors_read - dat], ecx |
add edx, 0x1FF |
shr edx, 9 |
mov [bp + filesize_sectors - dat], edx |
cmp edx, ecx |
seta al |
mov ah, 0 |
push ax |
call read_file_chunk |
continue_load_common_end: |
mov [bp + cur_chunk_ptr - dat], si |
pop bx |
mov ax, word [bp + filesize - dat] |
mov dx, word [bp + filesize+2 - dat] |
jnc @f |
mov bl, 3 ; read error |
@@: |
ret |
continue_load_file: |
; es:bx -> buffer for output, ecx = cx = number of sectors |
mov si, [bp + cur_chunk_ptr - dat] |
push ecx |
add ecx, [bp + sectors_read - dat] |
mov [bp + sectors_read - dat], ecx |
cmp [bp + filesize_sectors - dat], ecx |
pop ecx |
seta al |
mov ah, 0 |
push ax |
push continue_load_common_end |
push ss |
pop ds |
cmp [bp + cur_chunk_resident - dat], ah |
jnz .nonresident |
.resident: |
mov ax, word [bp + num_sectors - dat] |
jmp read_file_chunk.resident.continue |
.nonresident: |
mov eax, [bp + cur_cluster - dat] |
mov edx, [bp + num_sectors - dat] |
add eax, [bp + cur_delta - dat] |
jmp read_file_chunk.nonresident.continue |
fat_scan_for_filename: |
; in: ss:si -> 11-bytes FAT name |
; in: ds: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 |
push ds |
pop es |
xor di, di |
push cx |
jcxz .noent |
.loop: |
cmp byte [di], 0 |
jz .notfound |
test byte [di+11], 8 ; volume label? |
jnz .cont ; ignore volume labels |
pusha |
mov cx, 11 |
repz cmps byte [ss:si], byte [es:di] |
popa |
jz .done |
.cont: |
add di, 0x20 |
loop .loop |
.noent: |
inc cx ; clear ZF flag |
.notfound: |
stc |
.done: |
pop cx |
ret |
fat12_get_next_cluster: |
; in: ax = cluster (high word of eax is zero) |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
push si |
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 |
fat16_get_next_cluster: |
; in: ax = cluster (high word of eax is zero) |
; out: if there is next cluster: CF=1, ax = next cluster |
; out: if there is no next cluster: CF=0 |
; each sector contains 200h bytes = 100h FAT entries |
; so ah = # of sector, al = offset in sector |
push si |
mov si, ax |
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:0x3400+si], 0 ; sector already loaded? |
jnz .noread |
; load corresponding sector, try all FATs if disk read error detected |
pusha |
movzx di, byte [ss:0x3210] ; BPB_NumFATs |
xor bx, bx |
mov ax, [ss:0x320E] ; BPB_RsvdSecCnt |
xor dx, dx |
add ax, si |
adc dx, bx |
@@: |
push es |
push dx ax |
pop eax |
mov cx, 1 ; read 1 sector |
call read |
pop es |
jnc @f |
add ax, [ss:0x3216] ; BPB_FATSz16 |
adc dx, bx |
dec di |
jnz @b |
..found_disk_error: |
mov si, disk_error_msg |
jmp find_error_si |
@@: |
popa |
.noread: |
mov si, ax |
and si, 0xFF |
add si, si |
mov ax, [es:si] |
pop es |
cmp ax, 0xFFF7 |
pop si |
ret |
fat32_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 |
push ax |
shr eax, 7 |
; eax = FAT sector number; look in cache |
push si |
mov si, cache1head |
call cache_lookup |
pop si |
jnc .noread |
; read FAT, try all FATs if disk read error detected |
push es |
pushad |
movzx edx, word [ss:0x320E] ; BPB_RsvdSecCnt |
add eax, edx |
movzx si, byte [ss:0x3210] ; BPB_NumFATs |
@@: |
lea cx, [di - 0x3400 + (0x6000 shr (9-3))] |
shl cx, 9-3 |
mov es, cx |
xor bx, bx |
mov cx, 1 |
call read |
jnc @f |
add eax, [ss:0x3224] ; BPB_FATSz32 |
dec si |
jnz @b |
jmp ..found_disk_error |
@@: |
popad |
pop es |
.noread: |
; get requested item |
lea ax, [di - 0x3400 + (0x6000 shr (9-3))] |
pop di |
and di, 0x7F |
shl di, 2 |
shl ax, 9-3 |
push ds |
mov ds, ax |
and byte [di+3], 0x0F |
mov eax, [di] |
pop ds |
pop di |
;and eax, 0x0FFFFFFF |
cmp eax, 0x0FFFFFF7 |
ret |
/kernel/trunk/bootloader/extended_primary_loader/after_win/kordldr.win.txt |
---|
0,0 → 1,391 |
; 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. |
;***************************************************************************** |
Íåò ïîâåñòè ïå÷àëüíåå íà ñâåòå, |
×åì ïîâåñòü î çàêëèíèâøåì Reset'å... |
Çàãðóç÷èê äëÿ FAT- è NTFS-òîìîâ äëÿ ñëó÷àåâ, êîãäà îñíîâíîé áóòñåêòîð çàãðóæàåò |
Windows, äëÿ íîñèòåëåé ñ ðàçìåðîì ñåêòîðà 512 áàéò. |
===================================================================== |
Òðåáîâàíèÿ äëÿ ðàáîòû: |
1) Âñå èñïîëüçóåìûå ôàéëû äîëæíû áûòü ÷èòàáåëüíû. |
2) Ìèíèìàëüíûé ïðîöåññîð - 80386. |
3) Â ñèñòåìå äîëæíî áûòü êàê ìèíèìóì 592K ñâîáîäíîé áàçîâîé ïàìÿòè. |
4) Ïóòè ê èñïîëüçóåìûì ôàéëàì íå äîëæíû ñîäåðæàòü ñèìâîëè÷åñêèõ ññûëîê NTFS |
(æ¸ñòêèå ññûëêè äîïóñêàþòñÿ). |
5) Èñïîëüçóåìûå ôàéëû íå äîëæíû áûòü ñæàòûìè èëè ðàçðåæåííûìè ôàéëàìè |
(àêòóàëüíî äëÿ NTFS, äëÿ FAT âûïîëíåíî àâòîìàòè÷åñêè). |
===================================================================== |
Äîêóìåíòàöèÿ â òåìó (ññûëêè ïðîâåðÿëèñü íà âàëèäíîñòü 08.08.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 |
ñïåöèôèêàöèÿ NTFS: file://C:/windows/system32/drivers/ntfs.sys |
è file://C:/ntldr ëèáî file://C:/bootmgr |
íåîôèöèàëüíîå îïèñàíèå NTFS: http://sourceforge.net/project/showfiles.php?group_id=13956&package_id=16543 |
îôèöèàëüíàÿ ñïåöèôèêàöèÿ ðàñøèðåíèÿ 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 |
îôèöèàëüíîå îïèñàíèå bcdedit äëÿ Vista: http://www.microsoft.com/whdc/system/platform/firmware/bcdedit_reff.mspx |
îôèöèàëüíîå îïèñàíèå ðàáîòû ñ áàçîé äàííûõ çàãðóç÷èêà Vista: http://www.microsoft.com/whdc/system/platform/firmware/bcd.mspx |
ôîðìàò òàáëèöû ðàçäåëîâ æ¸ñòêîãî äèñêà: http://www.microsoft.com/technet/prodtechnol/windows2000serv/reskit/prork/prcb_dis_qxql.mspx |
===================================================================== |
Ñõåìà èñïîëüçóåìîé ïàìÿòè: |
600-2000 êîä çàãðóç÷èêà (è äàííûå) |
2000-3000 ñòåê |
3000-3200 ñåêòîð MBR |
3200-3400 áóòñåêòîð ëîãè÷åñêîãî äèñêà |
3400-3C00 èíôîðìàöèÿ î êýøå äëÿ òàáëèö FAT16/FAT32: |
äëÿ FAT16 - ìàññèâ íà 0x100 áàéò, êàæäûé áàéò ðàâåí |
0 èëè 1 â çàâèñèìîñòè îò òîãî, çàãðóæåí ëè |
ñîîòâåòñòâóþùèé ñåêòîð òàáëèöû FAT16; |
äëÿ FAT32 - 100h âõîäîâ ïî 8 áàéò: 4 áàéòà |
(äâå ññûëêè - âïåð¸ä è íàçàä) äëÿ îðãàíèçàöèè L2-ñïèñêà |
âñåõ ïðî÷èòàííûõ ñåêòîðîâ â ïîðÿäêå âîçðàñòàíèÿ |
ïîñëåäíåãî âðåìåíè èñïîëüçîâàíèÿ + 4 áàéòà äëÿ íîìåðà |
ñåêòîðà; ïðè ïåðåïîëíåíèè êýøà âûêèäûâàåòñÿ ýëåìåíò èç |
ãîëîâû ñïèñêà, òî åñòü òîò, ê êîòîðîìó äîëüøå âñåõ |
íå áûëî îáðàùåíèé |
3400-3440 èíôîðìàöèÿ î êýøå äëÿ ôàéëîâûõ çàïèñåé NTFS â |
òàêîì æå ôîðìàòå, êàê è êýø äëÿ FAT32, íî íà 8 âõîäîâ |
3480-34C0 çàãîëîâêè äëÿ êýøåé çàïèñåé èíäåêñà NTFS |
3500-3D00 èíôîðìàöèÿ î êýøàõ çàïèñåé èíäåêñà NTFS: ñ êàæäîé |
ôàéëîâîé çàïèñüþ ñâÿçàí ñâîé êýø äëÿ |
ñîîòâåòñòâóþùåãî èíäåêñà |
4000-8000 ìåñòî äëÿ èíôîðìàöèè îá àòðèáóòàõ äëÿ NTFS |
60000-80000 òàáëèöà FAT12 / ìåñòî ïîä òàáëèöó FAT16 / |
êýø äëÿ òàáëèöû FAT32 / êýø äëÿ ñòðóêòóð NTFS |
80000-90000 òåêóùèé ðàññìàòðèâàåìûé êëàñòåð |
90000-92000 FAT: êýø äëÿ êîðíåâîé ïàïêè |
92000-... FAT: êýø äëÿ íåêîðíåâûõ ïàïîê (êàæäîé ïàïêå îòâîäèòñÿ |
2000h áàéò = 100h âõîäîâ, îäíîâðåìåííî â êýøå |
ìîæåò íàõîäèòüñÿ íå áîëåå 7 ïàïîê; |
òî÷íûé ðàçìåð îïðåäåëÿåòñÿ ðàçìåðîì äîñòóïíîé |
ôèçè÷åñêîé ïàìÿòè - êàê ïðàâèëî, íåïîñðåäñòâåííî |
ïåðåä A0000 ðàçìåùàåòñÿ EBDA, Extended BIOS Data Area) |
===================================================================== |
Îñíîâíîé ïðîöåññ çàãðóçêè. |
0a. Çàãðóçêà èç-ïîä DOS è Win9x: óñòàíîâêà kordldr.win îñóùåñòâëÿåòñÿ |
ðàçìåùåíèåì êîìàíäû install=c:\kordldr.win â ïåðâîé ñòðîêå config.sys; |
ïðè ýòîì îñíîâíîé çàãðóç÷èê ñèñòåìû çàãðóæàåò kordldr.win êàê îáû÷íûé |
com-ôàéë, â êàêîé-òî ñåãìåíò ïî ñìåùåíèþ 100h è ïåðåäà¸ò óïðàâëåíèå |
â íà÷àëî êîäà (xxxx:0100). |
0á. Çàãðóçêà èç-ïîä WinNT/2000/XP: óñòàíîâêà kordldr.win îñóùåñòâëÿåòñÿ |
äîáàâëåíèåì ñòðîêè íàïîäîáèå c:\kordldr.win="KordOS" â ñåêöèþ |
[operating systems] ôàéëà boot.ini; åñëè çàãðóæàåìûé ôàéë èìååò ðàçìåð |
íå ìåíåå 8 Êá (0x2000 áàéò) è ïî ñìåùåíèþ 3 ñîäåðæèò ñèãíàòóðó 'NTFS' |
(â ñëó÷àå kordldr.win òàê è åñòü), òî îñíîâíîé çàãðóç÷èê êàæäîé èç |
ýòèõ ñèñòåì çàãðóæàåò kordldr.win ïî àäðåñó 0D00:0000 è ïåðåäà¸ò |
óïðàâëåíèå íà àäðåñ 0D00:0256. |
0â. Çàãðóçêà èç-ïîä Vista: óñòàíîâêà kordldr.win îñóùåñòâëÿåòñÿ ìàíèïóëÿöèÿìè |
ñ áàçîé äàííûõ îñíîâíîãî çàãðóç÷èêà ÷åðåç bcdedit è ïîäðîáíî îïèñàíà â |
èíñòðóêöèè ê kordldr.win; îñíîâíîé çàãðóç÷èê çàãðóæàåò öåëèêîì |
kordldr.win ïî àäðåñó 0000:7C00 è ïåðåäà¸ò óïðàâëåíèå â íà÷àëî êîäà. |
1. Ïðè çàãðóçêå èç-ïîä DOS/9x îñíîâíîé çàãðóç÷èê íå îæèäàåò, ÷òî çàãðóæåííàÿ |
èì ïðîãðàììà îêàæåòñÿ â ñâîþ î÷åðåäü çàãðóç÷èêîì, è â ýòîì ñëó÷àå |
kordldr.win îêàçûâàåòñÿ â óñëîâèÿõ, êîãäà îñíîâíîé çàãðóç÷èê óæå |
óñòàíîâèë êàêîå-òî îêðóæåíèå, â ÷àñòíîñòè, ïåðåõâàòèë íåêîòîðûå |
ïðåðûâàíèÿ. Ïîýòîìó ïåðåä îñòàëüíûìè äåéñòâèÿìè çàãðóç÷èê äîëæåí |
âîññòàíîâèòü ñèñòåìó â íà÷àëüíîå ñîñòîÿíèå. (Ïðè çàãðóçêå ïîä |
NT-ëèíåéêîé òàêîé ïðîáëåìû íå âîçíèêàåò, ïîñêîëüêó òàì îñíîâíîé |
çàãðóç÷èê íè÷åãî â ñèñòåìå íå òðîãàåò.) Ïîýòîìó ïåðåä ñîáñòâåííî |
èíèöèàëèçàöèåé KordOS ïðè ðàáîòå èç-ïîä DOS/9x ïðîèçâîäÿòñÿ |
äîïîëíèòåëüíûå äåéñòâèÿ. Ïåðâûì äåëîì kordldr ïðîâåðÿåò, êàêîé èç |
ñëó÷àåâ 0à è 0â èìååò ìåñòî (ñëó÷àé 0á îòëè÷àåòñÿ òåì, ÷òî ïåðåäà¸ò |
óïðàâëåíèå íå íà íà÷àëî êîäà): îïðåäåëÿåò çíà÷åíèå ip (êîìàíäà call |
ïîìåùàåò â ñòåê àäðåñ ñëåäóþùåé ïîñëå call èíñòðóêöèè, êîìàíäà pop si |
âûòàëêèâàåò åãî â ðåãèñòð si), è åñëè îíî ðàâíî 100h, òî kordldr |
çàãðóæåí êàê com-ôàéë èç-ïîä DOS/9x. Òîãäà îí ñïðàøèâàåò ïîäòâåðæäåíèÿ |
ó ïîëüçîâàòåëÿ (ïîñêîëüêó â ýòîé ñõåìå kordldr çàãðóæàåòñÿ âñåãäà, |
îí äîëæåí îñòàâèòü âîçìîæíîñòü ïðîäîëæèòü çàãðóçêó DOS/9x). Åñëè |
ïîëüçîâàòåëü õî÷åò ïðîäîëæèòü îáû÷íóþ çàãðóçêó, kordldr çàâåðøàåòñÿ. |
Èíà÷å èñïîëüçóåòñÿ òîò ôàêò, ÷òî ïðè âûäà÷å ïðåðûâàíèÿ ïåðåçàãðóçêè |
int 19h ñèñòåìà ïðåäâàðèòåëüíî ñíèìàåò âñå ñâîè ïåðåõâàòû BIOSîâñêèõ |
ïðåðûâàíèé, à ïîòîì â ñâîþ î÷åðåäü âûäà¸ò int 19h óæå BIOSó. Òàê ÷òî |
kordldr óñòàíàâëèâàåò ñâîé îáðàáîò÷èê òðàññèðîâî÷íîãî ïðåðûâàíèÿ, |
óñòàíàâëèâàåò ôëàã òðàññèðîâêè è ïåðåäà¸ò óïðàâëåíèå DOSîâñêîìó |
îáðàáîò÷èêó. Îáðàáîò÷èê òðàññèðîâî÷íîãî ïðåðûâàíèÿ íè÷åãî íå äåëàåò |
äî òåõ ïîð, ïîêà ñëåäóþùåé èíñòðóêöèåé íå îêàçûâàåòñÿ int 19h, à |
â ýòîò ìîìåíò îòáèðàåò óïðàâëåíèå è ïðîäîëæàåò çàãðóçêó KordOS. |
Ïðè ýòîì BIOSîâñêèå îáðàáîò÷èêè âîññòàíîâëåíû çà èñêëþ÷åíèåì, |
áûòü ìîæåò, ïðåðûâàíèÿ òàéìåðà int 8, êîòîðîå, âîçìîæíî, âîññòàíîâëåíî |
äî êîìàíäû jmp far íà îðèãèíàëüíûé îáðàáîò÷èê.  ïîñëåäíåì ñëó÷àå åãî |
íóæíî âîññòàíîâèòü ÿâíî. |
2. Çàãðóç÷èê ïåðåìåùàåò ñâîé êîä íà àäðåñ 0000:0600. |
3. (ìåòêà real_entry) Çàãðóç÷èê óñòàíàâëèâàåò ñåãìåíòíûå ðåãèñòðû ds = es = 0, |
íàñòðàèâàåò ñòåê ss:sp = 0000:3000 è óñòàíàâëèâàåò bp òàê, ÷òîáû |
âñå äàííûå ìîæíî áûëî àäðåñîâàòü ÷åðåç [bp+N] ñ îäíîáàéòîâûì N |
(â äàëüíåéøåì îíè òàê è áóäóò àäðåñîâàòüñÿ äëÿ îñâîáîæäåíèÿ ds è |
ýêîíîìèè íà ðàçìåðå êîäà). Ðàçðåøàåò ïðåðûâàíèÿ íà ñëó÷àé, åñëè |
îíè áûëè çàïðåùåíû. Âûäà¸ò ñîîáùåíèå î íà÷àëå çàãðóçêè, íà÷èíàþùååñÿ |
ñ âåñ¸ëîé ðîæèöû (ñèìâîë ñ ASCII-êîäîì 2). |
4. Îïðåäåëÿåò õàðàêòåðèñòèêè æ¸ñòêîãî äèñêà, óêàçàííîãî â êà÷åñòâå |
çàãðóçî÷íîãî: ïðîâåðÿåò ïîääåðæêó LBA (ôóíêöèÿ 41h ïðåðûâàíèÿ 13h), |
åñëè LBA íå ïîääåðæèâàåòñÿ, òî îïðåäåëÿåò ãåîìåòðèþ - ÷èñëî äîðîæåê |
è ÷èñëî ñåêòîðîâ íà äîðîæêå (ôóíêöèÿ 8 ïðåðûâàíèÿ 13h), ýòè ïàðàìåòðû |
íóæíû ôóíêöèè ÷òåíèÿ ñ äèñêà. |
5. (ìåòêà new_partition_ex) Óñòðàèâàåò öèêë ïî ðàçäåëàì æ¸ñòêîãî äèñêà. |
Öåëü öèêëà - äëÿ êàæäîãî ëîãè÷åñêîãî äèñêà ïîïûòàòüñÿ çàãðóçèòüñÿ ñ |
íåãî (äåéñòâèÿ ïî çàãðóçêå ñ êîíêðåòíîãî ëîãè÷åñêîãî äèñêà íà÷èíàþòñÿ |
ñ ìåòêè not_extended), ïðè îøèáêå çàãðóçêè óïðàâëåíèå ïåðåäà¸òñÿ |
íàçàä ýòîìó öèêëó (ìåòêà next_partition), è ïîèñê ïîäõîäÿùåãî ðàçäåëà |
ïðîäîëæàåòñÿ. Íà âûõîäå çàïîëíÿåòñÿ îäíà ïåðåìåííàÿ partition_start, |
èìåþùàÿ ñìûñë íà÷àëà òåêóùåãî ðàññìàòðèâàåìîãî ëîãè÷åñêîãî äèñêà, |
íî ïî õîäó äåëà èç-çà ïðèêîëîâ òàáëèö ðàçäåëîâ èñïîëüçóþòñÿ åù¸ ÷åòûðå |
ïåðåìåííûõ. cur_partition_ofs - ôàêòè÷åñêè ñ÷¸ò÷èê öèêëà, ôîðìàëüíî |
óêàçàòåëü íà òåêóùèé âõîä â òåêóùåé çàãðóçî÷íîé çàïèñè. Ñàìà |
çàãðóçî÷íàÿ çàïèñü ñ÷èòûâàåòñÿ â ïàìÿòü íà÷èíàÿ ñ àäðåñà 3000h. |
Òðè îñòàâøèõñÿ íóæíû äëÿ ïðàâèëüíîé ðàáîòû ñ ðàñøèðåííûìè ðàçäåëàìè. |
 êàæäîé çàãðóçî÷íîé çàïèñè ïîìåùàåòñÿ íå áîëåå 4 çàïèñåé î ðàçäåëàõ. |
Ïîýòîìó ãëàâíîé çàãðóçî÷íîé çàïèñè, ðàçìåùàþùåéñÿ â ïåðâîì ôèçè÷åñêîì |
ñåêòîðå äèñêà, ìîæåò íå õâàòèòü, è îáû÷íî ñîçäà¸òñÿ òàê íàçûâàåìûé |
ðàñøèðåííûé ðàçäåë ñ ðàñøèðåííûìè çàãðóçî÷íûìè çàïèñÿìè, ôîðìàò |
êîòîðûõ ïî÷òè èäåíòè÷åí ãëàâíîé. Ðàñøèðåííûé ðàçäåë ìîæåò áûòü òîëüêî |
îäèí, íî â í¸ì ìîæåò áûòü ìíîãî ëîãè÷åñêèõ äèñêîâ è ðàñøèðåííûõ |
çàãðóçî÷íûõ çàïèñåé. Ðàñøèðåííûå çàãðóçî÷íûå çàïèñè îðãàíèçîâàíû |
â îäíîñâÿçíûé ñïèñîê, â êàæäîé òàêîé çàïèñè ïåðâûé âõîä óêàçûâàåò |
íà ñîîòâåòñòâóþùèé ëîãè÷åñêèé äèñê, à âòîðîé - íà ñëåäóþùóþ ðàñøèðåííóþ |
çàãðóçî÷íóþ çàïèñü. |
Ïðè ýòîì â ãëàâíîé çàãðóçî÷íîé çàïèñè âñå àäðåñà ðàçäåëîâ ÿâëÿþòñÿ |
àáñîëþòíûìè íîìåðàìè ñåêòîðîâ. Â ðàñøèðåííûõ æå çàïèñÿõ àäðåñà ðàçäåëîâ |
îòíîñèòåëüíû, ïðè÷¸ì ñ ðàçíûìè áàçàìè: àäðåñ ëîãè÷åñêîãî äèñêà |
óêàçûâàåòñÿ îòíîñèòåëüíî ðàñøèðåííîé çàïèñè, à àäðåñ ñëåäóþùåé |
ðàñøèðåííîé çàïèñè óêàçûâàåòñÿ îòíîñèòåëüíî íà÷àëà ðàñøèðåííîãî |
ðàçäåëà. Òàêîé ðàçíîáîé âûãëÿäèò íåñêîëüêî ñòðàííî, íî èìååò ìåñòî |
áûòü. Òðè îñòàâøèõñÿ ïåðåìåííûõ ñîäåðæàò: extended_part_start - |
íà÷àëî ðàñøèðåííîãî ðàçäåëà; extended_parent - òåêóùàÿ ðàññìàòðèâàåìàÿ |
ðàñøèðåííàÿ çàãðóçî÷íàÿ çàïèñü; extended_part_cur - ñëåäóþùàÿ |
çàãðóçî÷íàÿ çàïèñü äëÿ ðàññìîòðåíèÿ. |
Öèêë âûãëÿäèò òàê: ïðîñìàòðèâàþòñÿ âñå ðàçäåëû, óêàçàííûå â òåêóùåé |
(ãëàâíîé èëè ðàñøèðåííîé) çàãðóçî÷íîé çàïèñè; äëÿ íîðìàëüíûõ ðàçäåëîâ |
(îíè æå ëîãè÷åñêèå äèñêè) ïðîèñõîäèò ïåðåõîä íà not_extended, ãäå |
óñòàíàâëèâàåòñÿ partition_start è íà÷èíàåòñÿ ñîáñòâåííî çàãðóçêà |
(ïîñëåäóþùèå øàãè); ïðè âñòðå÷å ñ ðàçäåëîì, òèï êîòîðîãî óêàçûâàåò |
íà ðàñøèðåííîñòü (5 èëè 0xF), êîä çàïîìèíàåò íà÷àëî ýòîãî ðàçäåëà |
(â ãëàâíîé çàãðóçî÷íîé çàïèñè òàêîé òèï îçíà÷àåò ðàñøèðåííûé ðàçäåë, |
â ðàñøèðåííîé - òîëüêî óêàçàòåëü íà ñëåäóþùóþ ðàñøèðåííóþ çàïèñü, |
â îáîèõ ñëó÷àÿõ îí ìîæåò âñòðåòèòüñÿ òîëüêî îäèí ðàç â äàííîé çàïèñè); |
êîãäà êîä äîõîäèò äî êîíöà ñïèñêà, âñå íîðìàëüíûå ðàçäåëû, îïèñûâàåìûå |
â ýòîé çàïèñè, óæå ïðîñìîòðåíû, òàê ÷òî êîä ñ ÷èñòîé ñîâåñòüþ ïåðåõîäèò |
ê ñëåäóþùåé ðàñøèðåííîé çàïèñè. Åñëè îí å¸ íå âñòðåòèë, çíà÷èò, óæå |
âñå ëîãè÷åñêèå ðàçäåëû áûëè ïîäâåðãíóòû ïîïûòêàì çàãðóçèòüñÿ, è âñå |
áåçðåçóëüòàòíî, òàê ÷òî âûâîäèòñÿ ðóãàòåëüñòâî è ðàáîòà îñòàíàâëèâàåòñÿ |
(jmp $). |
Ìîæåò âîçíèêíóòü âîïðîñ, çà÷åì íóæíà òàêàÿ ñëîæíàÿ ñõåìà è ïî÷åìó |
íåëüçÿ óçíàòü íóæíûé ëîãè÷åñêèé äèñê çàðàíåå èëè õîòÿ áû îãðàíè÷èòüñÿ |
ïåðâûì ïîïàâøèìñÿ ëîãè÷åñêèì äèñêîì, íå êðóòÿ öèêë. Òàê âîò, âàðèàíò |
ñ ïðåäâàðèòåëüíûì îïðåäåëåíèåì íóæíîãî ðàçäåëà â äàííîì ñëó÷àå íå |
èñïîëüçóåòñÿ, ïîñêîëüêó ïîâë¸ê áû çà ñîáîé íåòðèâèàëüíûå ëèøíèå |
äåéñòâèÿ ïî óñòàíîâêå (â òåêóùåì âèäå óñòàíîâêó ìîæíî ïðîâåñòè âðó÷íóþ, |
è îíà ñâîäèòñÿ ê óêàçàíèþ ñèñòåìíîìó çàãðóç÷èêó íà ñóùåñòâîâàíèå |
kordldr); êñòàòè, â àëüòåðíàòèâíîé âåðñèè çàãðóçêè ïîñëå |
Windows-çàãðóç÷èêà, êîãäà óñòàíîâêà îñóùåñòâëÿåòñÿ íå âðó÷íóþ, à |
ñïåöèàëüíîé ïðîãðàììîé ïîä Windows, èñïîëüçóåòñÿ ìîäèôèöèðîâàííàÿ |
âåðñèÿ, â êîòîðîé êàê ðàç íà÷àëüíûé ôèçè÷åñêèé ñåêòîð íóæíîãî ðàçäåëà |
ïðîïèñûâàåòñÿ óñòàíîâùèêîì. Ñàì kordldr íå ìîæåò óñòàíîâèòü, ñ êàêîãî |
ðàçäåëà åãî çàãðóçèë Windows-çàãðóç÷èê (è âîîáùå ïîä NT/2000/XP îáÿçàí |
áûòü ôàéëîì íà äèñêå C:\). Âàðèàíò ñ ïåðâûì ïîïàâøèìñÿ ëîãè÷åñêèì |
äèñêîì áûë ðåàëèçîâàí â ïåðâîé âåðñèè çàãðóç÷èêà, íî ïî õîäó äåëà |
îáíàðóæèëîñü, ÷òî òàêè íóæíî êðóòèòü öèêë: âî-âòîðûõ, ìîæåò áûòü |
ïðèÿòíûì, ÷òî ñàìà ñèñòåìà ìîæåò ñòîÿòü âîâñå íå íà ñèñòåìíîì C:\, à è |
íà äðóãèõ äèñêàõ; âî-ïåðâûõ, äèñê C: ìîæåò è íå áûòü ïåðâûì ëîãè÷åñêèì |
ðàçäåëîì - Vista ëþáèò ñîçäàâàòü ñêðûòûé ïåðâè÷íûé ðàçäåë ïåðåä |
ñèñòåìíûì, è òîãäà äèñê C: ñòàíîâèòñÿ âòîðûì ëîãè÷åñêèì. |
6. Èçâåùàåò ïîëüçîâàòåëÿ î òîì, ÷òî ïðîèñõîäèò ïîïûòêà çàãðóçêè ñ î÷åðåäíîãî |
ëîãè÷åñêîãî äèñêà. |
7. ×èòàåò ïåðâûé ñåêòîð ëîãè÷åñêîãî äèñêà è îïðåäåëÿåò ôàéëîâóþ ñèñòåìó. |
È â FAT, è â NTFS ïîëå ñî ñìåùåíèåì +11 ñîäåðæèò ÷èñëî áàéò â ñåêòîðå |
è äîëæíî ñîâïàäàòü ñ õàðàêòåðèñòèêîé ôèçè÷åñêîãî íîñèòåëÿ, òî åñòü |
200h áàéò. È â FAT, è â NTFS ïîëå ñî ñìåùåíèåì +13 ñîäåðæèò ÷èñëî |
ñåêòîðîâ â êëàñòåðå è äîëæíî áûòü ñòåïåíüþ äâîéêè. |
Êðèòåðèé NTFS: ïîëå ñî ñìåùåíèåì +3 ñîäåðæèò ñòðîêó NTFS è ïîëå ñî |
ñìåùåíèåì +16 íóëåâîå (â FAT îíî ñîäåðæèò ÷èñëî òàáëèö FAT è îáÿçàíî |
áûòü íåíóëåâûì). |
Êðèòåðèé FAT: çàãðóç÷èê âû÷èñëÿåò ÷èñëî êëàñòåðîâ, îïðåäåëÿåò |
ïðåäïîëîæèòåëüíûé òèï (FAT12/FAT16/FAT32) è ïðîâåðÿåò áàéò ïî ñìåùåíèþ |
+38 äëÿ FAT12/16, +66 äëÿ FAT32 (îí äîëæåí áûòü ðàâåí 0x29). |
Ïîñëå îïðåäåëåíèÿ òèïà ôàéëîâîé ñèñòåìû èçâåùàåò ïîëüçîâàòåëÿ îá |
îïðåäåë¸ííîì òèïå. Åñëè ôàéëîâàÿ ñèñòåìà íå ðàñïîçíàíà, âûäà¸ò |
ñîîòâåòñòâóþùåå ñîîáùåíèå è ïåðåõîäèò ê ñëåäóþùåìó ëîãè÷åñêîìó äèñêó. |
8a. Äëÿ FAT12-òîìîâ: çàñîâûâàåò â ñòåê èäåíòèôèêàòîð ôàéëîâîé ñèñòåìû - |
êîíñòàíòó '12'; óñòàíàâëèâàåò óêàçàòåëü íà ôóíêöèþ ïîëó÷åíèÿ ñëåäóþùåãî |
â öåïî÷êå FAT êëàñòåðà íà FAT12-îáðàáîò÷èê; ñ÷èòûâàåò â ïàìÿòü âñþ |
òàáëèöó FAT12 (îíà íå ïðåâîñõîäèò 0x1800 áàéò = 6 Êá), ïðè îøèáêå |
÷òåíèÿ ïûòàåòñÿ èñïîëüçîâàòü äðóãèå êîïèè FAT. |
8á. Äëÿ FAT16-òîìîâ: çàñîâûâàåò â ñòåê èäåíòèôèêàòîð ôàéëîâîé ñèñòåìû - |
êîíñòàíòó '16'; óñòàíàâëèâàåò óêàçàòåëü íà ôóíêöèþ ïîëó÷åíèÿ ñëåäóþùåãî |
â öåïî÷êå FAT êëàñòåðà íà FAT16-îáðàáîò÷èê; èíèöèàëèçèðóåò èíôîðìàöèþ |
î êýøå ñåêòîðîâ FAT (ìàññèâ áàéò ñ âîçìîæíûìè çíà÷åíèÿìè 0 è 1, |
îçíà÷àþùèìè, áûë ëè óæå çàãðóæåí ñîîòâåòñòâóþùèé ñåêòîð - âñåãî â |
òàáëèöå FAT16 íå áîëåå 0x100 ñåêòîðîâ) - íè îäèí ñåêòîð åù¸ íå |
çàãðóæåí, âñå áàéòû íóëåâûå. |
8â. Äëÿ FAT32-òîìîâ: çàñîâûâàåò â ñòåê èäåíòèôèêàòîð ôàéëîâîé ñèñòåìû - |
êîíñòàíòó '32'; óñòàíàâëèâàåò óêàçàòåëü íà ôóíêöèþ ïîëó÷åíèÿ ñëåäóþùåãî |
â öåïî÷êå FAT êëàñòåðà íà FAT16-îáðàáîò÷èê; èíèöèàëèçèðóåò èíôîðìàöèþ |
î êýøå ñåêòîðîâ FAT (ôîðìàò èíôîðìàöèè îïèñàí âûøå, â ðàñïðåäåëåíèè |
èñïîëüçóåìîé çàãðóç÷èêîì ïàìÿòè) - íè îäèí ñåêòîð åù¸ íå çàãðóæåí. |
8ã. Îáùåå äëÿ FAT-òîìîâ: îïðåäåëÿåò çíà÷åíèÿ ñëóæåáíûõ ïåðåìåííûõ |
root_start (ïåðâûé ñåêòîð êîðíåâîãî êàòàëîãà â FAT12/16, èãíîðèðóåòñÿ |
ïðè îáðàáîòêå FAT32-òîìîâ), data_start (íà÷àëî äàííûõ ñ ïîïðàâêîé, |
ââîäèìîé äëÿ òîãî, ÷òîáû êëàñòåð N íà÷èíàëñÿ ñ ñåêòîðà |
N*sectors_per_cluster+data_start), root_clus (ïåðâûé êëàñòåð êîðíåâîãî |
êàòàëîãà â FAT32, 0 â FAT12/16); óñòàíàâëèâàåò óêàçàòåëü íà ôóíêöèþ |
çàãðóçêè ôàéëà íà FAT-îáðàáîò÷èê. |
8ä. Äëÿ NTFS-òîìîâ: çàñîâûâàåò â ñòåê èäåíòèôèêàòîð ôàéëîâîé ñèñòåìû - |
êîíñòàíòó 'nt'; îïðåäåëÿåò çíà÷åíèå ñëóæåáíîé ïåðåìåííîé frs_size |
(ðàçìåð â áàéòàõ ôàéëîâîé çàïèñè, File Record Segment), äëÿ ïîëíîé |
êîððåêòíîñòè ïðîâåðÿåò, ÷òî ýòî çíà÷åíèå (ðàâíîå 0x400 áàéò íà âñåõ |
ðåàëüíûõ NTFS-òîìàõ - åäèíñòâåííûé ñïîñîá èçìåíèòü åãî çàêëþ÷àåòñÿ |
â ïåðåñîçäàíèè âñåõ ñèñòåìíûõ ñòðóêòóð âðó÷íóþ) íå ïðåâîñõîäèò 0x1000 |
è êðàòíî ðàçìåðó ñåêòîðà 0x200 áàéò; èíèöèàëèçèðóåò êýø ôàéëîâûõ |
çàïèñåé - íè÷åãî åù¸ íå çàãðóæåíî; ñ÷èòûâàåò ïåðâûé êëàñòåð $MFT |
è çàãðóæàåò èíôîðìàöèþ î ðàñïîëîæåíèè íà äèñêå âñåé òàáëèöû $MFT |
(àòðèáóò 0x80, $Data); óñòàíàâëèâàåò óêàçàòåëü íà ôóíêöèþ çàãðóçêè |
ôàéëà íà NTFS-îáðàáîò÷èê. |
9. (ìåòêà load_secondary) Âûçûâàåò ôóíêöèþ çàãðóçêè ôàéëà äëÿ ôàéëà âòîðè÷íîãî |
çàãðóç÷èêà. Ïðè îáíàðóæåíèè îøèáêè ïåðåõîäèò íà îáðàáîò÷èê îøèáîê ñ |
ñîîòâåòñòâóþùèì ñîîáùåíèåì. |
10. Óñòàíàâëèâàåò ðåãèñòðû äëÿ âòîðè÷íîãî çàãðóç÷èêà: al='h' (æ¸ñòêèé äèñê), |
ah=íîìåð äèñêà (äëÿ ãîòîâîãî áèíàðíèêà - 0 (BIOS-èäåíòèôèêàòîð 80h), |
ìîæåò áûòü èçìåí¸í ïóò¸ì ìîäèôèêàöèè êîíñòàíòû â èñõîäíèêå èëè |
ñïåöèàëüíûì óñòàíîâùèêîì), bx=èäåíòèôèêàòîð ôàéëîâîé ñèñòåìû (áåð¸òñÿ |
èç ñòåêà, êóäà ðàíåå áûë çàñóíóò íà øàãå 8), ds:si=óêàçàòåëü íà |
callback-ôóíêöèþ. |
11. Ïåðåäà¸ò óïðàâëåíèå âòîðè÷íîìó çàãðóç÷èêó äàëüíèì ïåðåõîäîì íà 1000:0000. |
Ôóíêöèÿ îáðàòíîãî âûçîâà äëÿ âòîðè÷íîãî çàãðóç÷èêà: |
ïðåäîñòàâëÿåò âîçìîæíîñòü ÷òåíèÿ ôàéëà. |
Âõîä è âûõîä îïèñàíû â ñïåöèôèêàöèè íà çàãðóç÷èê. |
×òåíèå ôàéëà: |
1. Ñîõðàíÿåò ñòåê âûçûâàþùåãî êîäà è óñòàíàâëèâàåò ñâîé ñòåê: |
ss:sp = 0:3000, bp=dat: ïàðà ss:bp ïðè ðàáîòå ñ îñòàëüíûì |
êîäîì äîëæíà óêàçûâàòü íà 0:dat. |
2. Ðàçáèðàåò ïåðåäàííûå ïàðàìåòðû è âûçûâàåò ïðîöåäóðó çàãðóçêè ôàéëà. |
3. Âîññòàíàâëèâàåò ñòåê âûçûâàþùåãî êîäà è âîçâðàùàåò óïðàâëåíèå. |
Âñïîìîãàòåëüíûå ïðîöåäóðû. |
Ïðîöåäóðà ÷òåíèÿ ñåêòîðîâ (read): |
íà âõîäå äîëæíî áûòü óñòàíîâëåíî: |
ss:bp = 0:dat |
es:bx = óêàçàòåëü íà íà÷àëî áóôåðà, êóäà áóäóò ïðî÷èòàíû äàííûå |
eax = ñòàðòîâûé ñåêòîð (îòíîñèòåëüíî íà÷àëà ëîãè÷åñêîãî äèñêà) |
cx = ÷èñëî ñåêòîðîâ (äîëæíî áûòü áîëüøå íóëÿ) |
íà âûõîäå: es:bx óêàçûâàåò íà êîíåö áóôåðà, â êîòîðûé áûëè ïðî÷èòàíû äàííûå, |
ôëàã CF óñòàíîâëåí, åñëè âîçíèêëà îøèáêà ÷òåíèÿ |
1. Ïåðåâîäèò ñòàðòîâûé ñåêòîð (îòñ÷èòûâàåìûé îò íà÷àëà òîìà) â ñåêòîð íà |
óñòðîéñòâå, ïðèáàâëÿÿ íîìåð ïåðâîãî ñåêòîðà ëîãè÷åñêîãî äèñêà, |
íàéäåííûé ïðè ïåðåáîðå äèñêîâ. |
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. |
Ïðîöåäóðà îáðàáîòêè îøèáîê (find_error_si è find_error_sp): |
íà âõîäå: óêàçàòåëü íà ñîîáùåíèå îá îøèáêå â si ëèáî íà âåðõóøêå ñòåêà |
0. Åñëè âûçûâàåòñÿ find_error_si, îíà ïîìåùàåò ïåðåäàííûé óêàçàòåëü â ñòåê. |
1. Åñëè îøèáêà ïðîèçîøëà â ïðîöåññå ðàáîòû callback-ôóíêöèè, òî |
(ìåòêà error_in_callback) îáðàáîò÷èê ïðîñòî âîçâðàùàåò óïðàâëåíèå |
âûçâàâøåìó êîäó, ðàïîðòóÿ î íåíàéäåííîì ôàéëå. |
2. Åñëè æå îøèáêà ïðîèçîøëà äî ïåðåäà÷è óïðàâëåíèÿ âòîðè÷íîìó çàãðóç÷èêó, |
îáðàáîò÷èê âûâîäèò ñîîáùåíèå òèïà "Error: <òåêóùèé îáúåêò>: <îøèáêà>" |
è (âîññòàíîâèâ ñòåê) ïåðåõîäèò ê ñëåäóþùåìó ëîãè÷åñêîìó äèñêó. |
Ïðîöåäóðà ÷òåíèÿ ôàéëà/àòðèáóòà ïî èçâåñòíîìó ðàçìåùåíèþ íà äèñêå |
(read_file_chunk): |
íà âõîäå äîëæíî áûòü óñòàíîâëåíî: |
ds:si = óêàçàòåëü íà èíôîðìàöèþ î ðàçìåùåíèè |
es:bx = óêàçàòåëü íà íà÷àëî áóôåðà, êóäà áóäóò ïðî÷èòàíû äàííûå |
ecx = ëèìèò ÷èñëà ñåêòîðîâ äëÿ ÷òåíèÿ, ñòàðøåå ñëîâî äîëæíî áûòü 0 |
íà âûõîäå: es:bx óêàçûâàåò íà êîíåö áóôåðà, â êîòîðûé áûëè ïðî÷èòàíû äàííûå, |
ôëàã CF óñòàíîâëåí, åñëè âîçíèêëà îøèáêà ÷òåíèÿ |
1. Îïðåäåëÿåò, ÿâëÿåòñÿ ëè àòðèáóò ðåçèäåíòíûì (âîçìîæíî òîëüêî â NTFS |
è îçíà÷àåò, ÷òî äàííûå ôàéëà/àòðèáóòà óæå áûëè öåëèêîì ïðî÷èòàíû ïðè |
îáðàáîòêå èíôîðìàöèè î ôàéëå) èëè íåðåçèäåíòíûì (îçíà÷àåò, ÷òî äàííûå |
õðàíÿòñÿ ãäå-òî íà äèñêå, è èìååòñÿ èíôîðìàöèÿ î òîì, ãäå èìåííî). |
2. Äëÿ ðåçèäåíòíûõ àòðèáóòîâ (ìåòêà read_file_chunk.resident) ïðîñòî êîïèðóåò |
äàííûå ïî ìåñòó íàçíà÷åíèÿ (ñ ó÷¸òîì óêàçàííîãî ëèìèòà). |
3. Äëÿ íåðåçèäåíòíûõ àòðèáóòîâ èíôîðìàöèÿ ñîñòîèò èç ïàð <ðàçìåð î÷åðåäíîãî |
ôðàãìåíòà ôàéëà â êëàñòåðàõ, ñòàðòîâûé êëàñòåð ôðàãìåíòà>; ïðîöåäóðà |
÷èòàåò ôðàãìåíòû, ïîêà ôàéë íå çàêîí÷èòñÿ èëè ïîêà íå áóäåò äîñòèãíóò |
óêàçàííûé ëèìèò. |
Ïðîöåäóðà ïðîñìîòðà êýøà (cache_lookup): |
íà âõîäå äîëæíî áûòü óñòàíîâëåíî: |
eax = èñêîìîå çíà÷åíèå |
ss:si = óêàçàòåëü íà ñòðóêòóðó-çàãîëîâîê êýøà |
íà âûõîäå: ss:di = óêàçàòåëü íà âõîä â êýøå; ôëàã CF óñòàíîâëåí, åñëè çíà÷åíèå |
áûëî òîëüêî ÷òî äîáàâëåíî, è ñáðîøåí, åñëè îíî óæå áûëî â êýøå. |
1. Ïðîñìàòðèâàåò êýø â ïîèñêàõ óêàçàííîãî çíà÷åíèÿ. Åñëè çíà÷åíèå íàéäåíî |
(ïðè ýòîì ôëàã CF îêàçûâàåòñÿ ñáðîøåííûì), ïåðåõîäèò ê øàãó 4. |
2. Åñëè êýø óæå çàïîëíåí, óäàëÿåò èç êýøà ñàìûé ñòàðûé âõîä (îí íàõîäèòñÿ â |
ãîëîâå äâóñâÿçíîãî ñïèñêà), èíà÷å äîáàâëÿåò ê êýøó åù¸ îäèí âõîä. |
3. Óñòàíàâëèâàåò â ïîëó÷åííîì âõîäå óêàçàííîå çíà÷åíèå. Óñòàíàâëèâàåò ôëàã |
CF, ïîñëåäóþùèå øàãè íå ìåíÿþò ñîñòîÿíèÿ ôëàãîâ. Ïåðåõîäèò ê øàãó 5. |
4. Óäàëÿåò âõîä èç ñïèñêà. |
5. Äîáàâëÿåò ñåêòîð â êîíåö ñïèñêà (ñàìûé íîâûé âõîä). |
/kernel/trunk/bootloader/extended_primary_loader/after_win/ntfs.inc |
---|
0,0 → 1,587 |
; 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. |
;***************************************************************************** |
restore_usa: |
; Update Sequence Array restore |
; in: ds:bx -> USA-protected structure |
push bx |
lea di, [bx+1feh] |
mov cx, [bx+6] |
add bx, [bx+4] |
dec cx |
@@: |
mov ax, [bx+2] |
mov [di], ax |
inc bx |
inc bx |
add di, 200h |
loop @b |
pop bx |
ret |
find_attr: |
; in: ds:di->file record, ax=attribute |
; out: ds:di->attribute or di=0 if not found |
add di, [di+14h] |
.1: |
; attributes' codes are formally dwords, but all of them fit in word |
cmp word [di], -1 |
jz .notfound |
cmp word [di], ax |
jnz .continue |
; for $DATA attribute, scan only unnamed |
cmp ax, 80h |
jnz .found |
cmp byte [di+9], 0 |
jz .found |
.continue: |
add di, [di+4] |
jmp .1 |
.notfound: |
xor di, di |
.found: |
ret |
process_mcb_nonres: |
; in: ds:si->attribute, es:di->buffer |
; out: es:di->buffer end |
pushad |
pop di |
add si, [si+20h] |
xor ebx, ebx |
.loop: |
lodsb |
test al, al |
jz .done |
push invalid_read_request_string |
movzx cx, al |
shr cx, 4 |
jz find_error_sp |
xchg ax, dx |
and dx, 0Fh |
jz find_error_sp |
add si, cx |
add si, dx |
pop ax |
push si |
dec si |
movsx eax, byte [si] |
dec cx |
jz .l1e |
.l1: |
dec si |
shl eax, 8 |
mov al, [si] |
loop .l1 |
.l1e: |
xchg ebp, eax |
dec si |
movsx eax, byte [si] |
mov cx, dx |
dec cx |
jz .l2e |
.l2: |
dec si |
shl eax, 8 |
mov al, byte [si] |
loop .l2 |
.l2e: |
pop si |
add ebx, ebp |
; eax=length, ebx=disk block |
stosd |
mov eax, ebx |
stosd |
cmp di, 0x8000 - 12 |
jbe .loop |
..attr_overflow: |
mov si, fragmented_string |
jmp find_error_si |
.done: |
xor ax, ax |
stosw |
stosw |
push di |
popad |
ret |
load_attr: |
; in: ax=attribute, ds:bx->base record |
; out: if found: CF=0, attribute loaded to [freeattr], [freeattr] updated, |
; edx=size of attribute in bytes |
; out: if not found: CF=1 |
mov di, [bp + freeattr - dat] |
push ss |
pop es |
mov byte [es:di], 1 |
inc di |
cmp di, 0x8000 - 12 |
ja ..attr_overflow |
or edx, -1 ; file size is not known yet |
; scan for attribute |
push di |
mov di, bx |
add di, [di+14h] |
@@: |
call find_attr.1 |
test di, di |
jz .notfound1 |
cmp byte [di+8], 0 |
jnz .nonresident |
mov si, di |
pop di |
push ds |
jmp .resident |
.aux_resident: |
mov ax, ds |
mov si, di |
pop di ds bx ds edx |
push ss |
pop es |
push ds |
mov ds, ax |
; resident attribute |
.resident: |
dec di |
mov al, 0 |
stosb |
mov ax, [si+10h] |
stosw |
push di |
add di, ax |
cmp di, 0x8000 - 12 |
pop di |
ja ..attr_overflow |
movzx edx, ax ; length of attribute |
xchg ax, cx |
add si, [si+14h] |
rep movsb |
mov [bp + freeattr - dat], di |
pop ds |
ret |
.nonresident: |
; nonresident attribute |
cmp dword [di+10h], 0 |
jnz @b |
; read start of data |
mov si, di |
mov edx, [di+30h] ; size of attribute |
pop di |
call process_mcb_nonres |
sub di, 4 |
push di |
.notfound1: |
pop di |
push edx |
; $ATTRIBUTE_LIST is always in base file record |
cmp ax, 20h |
jz .nofragmented |
; try to load $ATTRIBUTE_LIST = 20h |
push ax |
mov ax, 20h |
push [bp + freeattr - dat] |
mov [bp + freeattr - dat], di |
push di |
call load_attr |
pop di |
pop [bp + freeattr - dat] |
pop ax |
jc .nofragmented |
push ds bx |
pusha |
mov si, di |
push ss |
pop ds |
push 0x8100 |
pop es |
xor ecx, ecx |
mov cl, 0x78 |
xor bx, bx |
push es |
call read_file_chunk |
pop ds |
jc ..found_disk_error |
test cx, cx |
jz ..attr_overflow |
popa |
push ss |
pop es |
xor bx, bx |
.1: |
cmp [bx], ax |
jnz .continue1 |
; only unnamed $DATA attributes! |
cmp ax, 80h |
jnz @f |
cmp byte [bx+6], 0 |
jnz .continue1 |
@@: |
cmp dword [bx+10h], 0 |
jz .continue1 |
cmp dword [bx+8], 0 |
jnz @f |
dec di |
cmp di, [bp + freeattr - dat] |
lea di, [di+1] |
jnz .continue1 |
@@: |
push ds di |
push ax |
mov eax, [bx+10h] |
mov ecx, [bx+8] |
call read_file_record |
pop ax |
mov di, [14h] |
.2: |
call find_attr.1 |
cmp byte [di+8], 0 |
jz .aux_resident |
cmp dword [di+10h], ecx |
jnz .2 |
mov si, di |
mov di, sp |
cmp dword [ss:di+8], -1 |
jnz @f |
push dword [si+30h] ; size of attribute |
pop dword [ss:di+8] |
@@: |
pop di |
call process_mcb_nonres |
sub di, 4 |
pop ds |
.continue1: |
add bx, [bx+4] |
cmp bx, dx |
jb .1 |
pop bx ds |
.nofragmented: |
pop edx |
dec di |
cmp di, [bp + freeattr - dat] |
jnz @f |
stc |
ret |
@@: |
inc di |
xor ax, ax |
stosw |
stosw |
mov [bp + freeattr - dat], di |
ret |
read_file_record: |
; in: eax = index of record |
; out: ds:0 -> record |
; find place in cache |
push di |
push si |
mov si, cache1head |
call cache_lookup |
pop si |
pushf |
sub di, 3400h |
shl di, 10-3 |
add di, 0x6000 |
mov ds, di |
popf |
pop di |
jnc .noread |
; read file record <eax> to ds:0 |
pushad |
push ds |
push es |
movzx ecx, [bp + frs_size - dat] |
shr cx, 9 |
mul ecx |
push ds |
pop es |
push ss |
pop ds |
mov si, 0x4000 |
xor bx, bx |
push [bp + cur_obj - dat] |
mov [bp + cur_obj - dat], mft_string |
push es |
call read_attr |
; initialize cache for $INDEX_ALLOCATION for this record |
pop si |
push si |
sub si, 0x6000 |
mov ax, si |
shr si, 10-3 |
shr ax, 2 |
add si, 3480h |
add ax, 3500h |
mov [si], si |
mov [si+2], si |
mov [si+4], ax |
pop ds |
call restore_usa |
pop [bp + cur_obj - dat] |
pop es |
pop ds |
popad |
.noread: |
ret |
read_attr: |
; in: eax = offset in sectors, ecx = size in sectors (<10000h), es:bx -> buffer, ds:si -> attribute |
push invalid_read_request_string |
cmp byte [si], 0 |
jnz .nonresident |
cmp eax, 10000h shr 9 |
jae find_error_sp |
shl ax, 9 |
shl cx, 9 |
cmp ax, [si+2] |
jae find_error_sp |
cmp cx, [si+2] |
ja find_error_sp |
add si, 3 |
add si, ax |
mov di, bx |
rep movsb |
pop ax |
ret |
.nonresident: |
inc si |
.loop: |
mov edx, dword [si] |
add si, 8 |
test edx, edx |
jz find_error_sp |
imul edx, [bp + sect_per_clust - dat] |
sub eax, edx |
jnc .loop |
add eax, edx |
sub edx, eax |
push cx |
cmp ecx, edx |
jb @f |
mov cx, dx |
@@: |
push bx |
mov ebx, [si-4] |
imul ebx, [bp + sect_per_clust - dat] |
add eax, ebx |
pop bx |
call read |
jc ..found_disk_error |
mov dx, cx |
pop cx |
xor eax, eax |
sub cx, dx |
jnz .loop |
pop ax |
ret |
load_file_ntfs: |
; in: ss:bp = 0:dat |
; in: es:bx = address to load file |
; in: ds:si -> ASCIIZ name |
; in: cx = limit in sectors |
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part has been loaded, bx=2 - file not found |
; out: dx:ax = file size (0xFFFFFFFF if file not found) |
push es bx cx |
mov eax, 5 ; root cluster |
mov [bp + cur_obj - dat], root_string |
.parse_dir_loop: |
push ds si |
call read_file_record |
; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP |
mov ax, [bp + freeattr - dat] |
mov [bp + index_root - dat], ax |
mov ax, 90h ; $INDEX_ROOT |
xor bx, bx |
call load_attr |
mov si, noindex_string |
jc find_error_si |
mov ax, [bp + freeattr - dat] |
mov [bp + index_alloc - dat], ax |
mov ax, 0A0h ; $INDEX_ALLOCATION |
call load_attr |
jnc @f |
mov [bp + index_alloc - dat], bx |
@@: |
push ds |
; search for entry |
mov si, [bp + index_root - dat] |
push ss |
pop ds |
push 0x8100 |
pop es |
xor ecx, ecx |
mov cl, 0x78 |
xor bx, bx |
push es |
call read_file_chunk |
pop ds |
jc ..found_disk_error |
test cx, cx |
jz ..attr_overflow |
mov si, invalid_read_request_string |
cmp word [bx+10], 0 |
jnz find_error_si |
; calculate number of items in cache |
mov di, [bx+8] ; subnode_size |
mov ax, 0x4000 |
sub ax, word [bp + frs_size - dat] |
cwd |
div di |
test ax, ax |
jz find_error_si |
mov si, invalid_volume_msg |
test di, 0x1FF |
jnz find_error_si |
pop cx |
mov [bp + cur_index_seg - dat], cx |
shl ax, 3 |
sub cx, 6000h |
mov si, cx |
shr cx, 2 |
shr si, 10-3 |
add cx, ax |
add si, 3480h |
mov [bp + cur_index_cache - dat], si |
add cx, 3500h |
mov [ss:si+6], cx |
mov dx, di |
add bx, 10h |
.scan_record: |
add bx, [bx] |
.scan: |
test byte [bx+0Ch], 2 |
jnz .look_child |
movzx cx, byte [bx+50h] ; namelen |
lea di, [bx+52h] ; name |
push ds |
pop es |
pop si ds |
push ds si |
xor ax, ax |
.1: |
lodsb |
cmp al, '/' |
jnz @f |
mov al, 0 |
@@: |
cmp al, 'A' |
jb .nocapital |
cmp al, 'Z' |
ja .nocapital |
or al, 20h |
.nocapital: |
cmp al, 'a' |
jb .notletter |
cmp al, 'z' |
ja .notletter |
or byte [es:di], 20h |
.notletter: |
scasw |
loopz .1 |
jb .look_child |
ja @f |
cmp byte [si], 0 |
jz .file_found |
cmp byte [si], '/' |
jz .file_found |
@@: |
push es |
pop ds |
add bx, [bx+8] |
jmp .scan |
.look_child: |
push es |
pop ds |
test byte [bx+0Ch], 1 |
jz .not_found |
mov si, [bp + index_alloc - dat] |
test si, si |
jz .not_found |
add bx, [bx+8] |
mov eax, [bx-8] |
mov es, [bp + cur_index_seg - dat] |
push si |
mov si, [bp + cur_index_cache - dat] |
call cache_lookup |
pop si |
pushf |
mov bx, di |
mov bh, 0 |
shr bx, 3 |
imul bx, dx |
add bx, [bp + frs_size - dat] |
popf |
jnc .noread |
push es |
push dx |
push ss |
pop ds |
movzx ecx, dx |
shr cx, 9 |
mul [bp + sect_per_clust - dat] |
call read_attr |
pop dx |
pop es |
push es |
pop ds |
call restore_usa |
.noread: |
push es |
pop ds |
add bx, 18h |
jmp .scan_record |
.not_found: |
pop [bp + cur_obj - dat] |
mov si, error_not_found |
jmp find_error_si |
.file_found: |
pop [bp + cur_obj - dat] |
pop cx |
mov ax, [bp + index_root - dat] |
mov [bp + freeattr - dat], ax |
mov eax, [es:bx] |
test byte [es:bx+48h+3], 10h |
jz .regular_file |
cmp byte [si], 0 |
jz ..directory_error |
inc si |
jmp .parse_dir_loop |
.regular_file: |
cmp byte [si], 0 |
jnz ..notdir_error |
; read entry |
call read_file_record |
xor bx, bx |
mov ax, 80h |
call load_attr |
mov si, nodata_string |
jc find_error_si |
mov si, [bp + index_root - dat] |
mov [bp + freeattr - dat], si |
push ss |
pop ds |
jmp load_file_common_end |
/kernel/trunk/bootloader/extended_primary_loader/after_win |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/kernel/trunk/bootloader/extended_primary_loader/cdfs/bootsect.asm |
---|
0,0 → 1,1024 |
; 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. |
;***************************************************************************** |
jmp far 0:real_start |
; special text |
org $+0x7C00 |
real_start: |
; initialize |
xor ax, ax |
mov ss, ax |
mov sp, 0x7C00 |
mov ds, ax |
mov es, ax |
cld |
sti |
mov [bootdrive], dl |
; check LBA support |
mov ah, 41h |
mov bx, 55AAh |
int 13h |
mov si, aNoLBA |
jc err_ |
cmp bx, 0AA55h |
jnz err_ |
test cl, 1 |
jz err_ |
; get file system information |
; scan for Primary Volume Descriptor |
db 66h |
push 10h-1 |
pop eax |
pvd_scan_loop: |
mov cx, 1 |
inc eax |
mov bx, 0x1000 |
call read_sectors |
jnc @f |
fatal_read_err: |
mov si, aReadError |
err_: |
call out_string |
mov si, aPressAnyKey |
call out_string |
xor ax, ax |
int 16h |
int 18h |
jmp $ |
@@: |
push ds |
pop es |
cmp word [bx+1], 'CD' |
jnz pvd_scan_loop |
cmp word [bx+3], '00' |
jnz pvd_scan_loop |
cmp byte [bx+5], '1' |
jnz pvd_scan_loop |
; we have found ISO9660 descriptor, look for type |
cmp byte [bx], 1 ; Primary Volume Descriptor? |
jz pvd_found |
cmp byte [bx], 0xFF ; Volume Descriptor Set Terminator? |
jnz pvd_scan_loop |
; Volume Descriptor Set Terminator reached, no PVD found - fatal error |
mov si, no_pvd |
jmp err_ |
pvd_found: |
add bx, 80h |
mov ax, [bx] |
mov [lb_size], ax |
; calculate number of logical blocks in one sector |
mov ax, 800h |
cwd |
div word [bx] |
mov [lb_per_sec], ax |
; get location of root directory |
mov di, root_location |
movzx eax, byte [bx+1Dh] |
add eax, [bx+1Eh] |
stosd |
; get memory size |
int 12h |
mov si, nomem_str |
cmp ax, 71000h / 400h |
jb err_ |
shr ax, 1 |
sub ax, 60000h / 800h |
mov [size_rest], ax |
mov [free_ptr], 60000h / 800h |
; load path table |
; if size > 62K => it's very strange, avoid using it |
; if size > (size of cache)/2 => avoid using it too |
mov ecx, [bx+4] |
cmp ecx, 0x10000 - 0x800 |
ja nopathtable |
shr ax, 1 |
cmp ax, 0x20 |
jae @f |
shl ax, 11 |
cmp cx, ax |
ja nopathtable |
@@: |
; size is ok, try to load it |
mov [pathtable_size], cx |
mov eax, [bx+12] |
xor edx, edx |
div dword [lb_per_sec] |
imul dx, [bx] |
mov [pathtable_start], dx |
add cx, dx |
call cx_to_sectors |
xor bx, bx |
push 6000h |
pop es |
call read_sectors |
jc nopathtable |
; path table has been loaded |
inc [use_path_table] |
sub [size_rest], cx |
add [free_ptr], cx |
nopathtable: |
; init cache |
mov ax, [size_rest] |
mov [cache_size], ax |
mov ax, [free_ptr] |
mov [cache_start], ax |
; load secondary loader |
mov di, secondary_loader_info |
call load_file |
test bx, bx |
jnz noloader |
; set registers for secondary loader |
mov ah, [bootdrive] |
mov al, 'c' |
mov bx, 'is' |
mov si, callback |
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 |
noloader: |
mov si, aKernelNotFound |
jmp err_ |
read_sectors: |
; es:bx = pointer to data |
; eax = first sector |
; cx = number of sectors |
pushad |
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 |
db 66h |
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, [cs:bootdrive] |
mov ah, 42h |
int 13h |
jc diskreaderr |
; restore stack |
add sp, 10h |
; increase current sector & buffer; decrease number of sectors |
movzx esi, cx |
mov ax, es |
shl cx, 7 |
add ax, cx |
mov es, ax |
pop cx |
pop ax |
add eax, esi |
sub cx, si |
jnz do_read_sectors |
pop ds |
popad |
ret |
diskreaderr: |
add sp, 10h + 2*2 |
pop ds |
popad |
stc |
out_string.ret: |
ret |
out_string: |
; in: ds:si -> ASCIIZ string |
lodsb |
test al, al |
jz .ret |
mov ah, 0Eh |
mov bx, 7 |
int 10h |
jmp out_string |
aNoLBA db 'The drive does not support LBA!',0 |
aReadError db 'Read error',0 |
no_pvd db 'Primary Volume Descriptor not found!',0 |
nomem_str db 'No memory',0 |
aPressAnyKey db 13,10,'Press any key...',13,10,0 |
load_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 = 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) |
; parse path to the file |
lea si, [di+6] |
mov eax, [cs:root_location] |
cmp [cs:use_path_table], 0 |
jz parse_dir |
; scan for path in path table |
push di |
push 6000h |
pop es |
mov di, [cs:pathtable_start] ; es:di = pointer to current entry in path table |
mov dx, 1 ; dx = number of current entry in path table, start from 1 |
mov cx, [cs:pathtable_size] |
pathtable_newparent: |
mov bx, dx ; bx = number of current parent in path table: root = 1 |
scan_path_table_e: |
call is_last_component |
jnc path_table_scanned |
scan_path_table_i: |
cmp word [es:di+6], bx |
jb .next |
ja path_table_notfound |
call test_filename1 |
jc .next |
@@: |
lodsb |
cmp al, '/' |
jnz @b |
jmp pathtable_newparent |
.next: |
; go to next entry |
inc dx |
movzx ax, byte [es:di] |
add ax, 8+1 |
and al, not 1 |
add di, ax |
sub cx, ax |
ja scan_path_table_i |
path_table_notfound: |
pop di |
mov ax, -1 |
mov dx, ax |
mov bx, 2 ; file not found |
ret |
path_table_scanned: |
movzx eax, byte [es:di+1] |
add eax, [es:di+2] |
pop di |
parse_dir: |
; eax = logical block, ds:di -> information structure, ds:si -> file name |
; was the folder already read? |
push di ds |
push cs |
pop ds |
mov [cur_desc_end], 2000h |
mov bx, cachelist |
.scan1: |
mov bx, [bx+2] |
cmp bx, cachelist |
jz .notfound |
cmp [bx+4], eax |
jnz .scan1 |
.found: |
; yes; delete this item from the list (the following code will append this item to the tail) |
mov di, [bx] |
push word [bx+2] |
pop word [di+2] |
mov di, [bx+2] |
push word [bx] |
pop word [di] |
mov di, bx |
jmp .scan |
.notfound: |
; no; load first sector of the folder to get its size |
push eax |
push si |
mov si, 1 |
call load_phys_sector_for_lb_force |
mov bx, si |
pop si |
pop eax |
jnc @f |
; read error - return |
.readerr: |
pop ds |
.readerr2: |
pop di |
mov ax, -1 |
mov dx, ax |
mov bx, 3 |
ret |
@@: |
; first item of the folder describes the folder itself |
; do not cache too big folders: size < 64K and size <= (total cache size)/2 |
cmp word [bx+12], 0 |
jnz .nocache |
mov cx, [cache_size] ; cx = cache size in sectors |
shr cx, 1 ; cx = (cache size)/2 |
cmp cx, 0x20 |
jae @f |
shl cx, 11 |
cmp [bx+10], cx |
ja .nocache |
@@: |
; we want to cache this folder; get space for it |
mov cx, [bx+10] |
call cx_to_sectors |
jnz .yescache |
.nocache: |
push dword [bx+10] |
pop dword [cur_nocache_len] |
call lb_to_sector |
push ds |
pop es |
pop ds |
.nocache_loop: |
push eax |
mov dx, 1800h |
call scan_for_filename_in_sector |
mov cx, dx |
pop eax |
jnc .j_scandone |
sub cx, bx |
sub word [es:cur_nocache_len], cx |
sbb word [es:cur_nocache_len+2], 0 |
jb .j_scandone |
ja @f |
cmp word [es:cur_nocache_len], 0 |
jz .j_scandone |
@@: |
mov cx, 1 |
inc eax |
push es |
mov bx, 1000h |
call read_sectors |
pop es |
jc .readerr2 |
jmp .nocache_loop |
.j_scandone: |
jmp .scandone |
.yescache: |
push bx |
mov bx, [cachelist.head] |
.freeloop: |
cmp cx, [size_rest] |
jbe .sizeok |
@@: |
; if we are here: there is not enough free space, so we must delete old folders' data |
; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2). |
; one loop iteration: delete data of one folder |
pusha |
mov dx, [bx+10] |
mov es, dx ; es = segment of folder data to be deleted |
xor di, di |
mov ax, [bx+8] |
add ax, 0x7FF |
rcr ax, 1 |
shr ax, 10 |
push ax |
shl ax, 11-4 ; get number of paragraphs in folder data to be deleted |
mov cx, [cache_size] |
add cx, [cache_start] |
push ds |
push ax |
add ax, dx |
mov ds, ax |
pop ax |
shl cx, 11-4 |
sub cx, dx ; cx = number of paragraphs to be moved |
push si |
xor si, si |
; move cx paragraphs from ds:si to es:di to get free space in the end of cache |
@@: |
sub cx, 1000h |
jbe @f |
push cx |
mov cx, 8000h |
rep movsw |
mov cx, ds |
add cx, 1000h |
mov ds, cx |
mov cx, es |
add cx, 1000h |
mov es, cx |
pop cx |
jmp @b |
@@: |
add cx, 1000h |
shl cx, 3 |
rep movsw |
pop si |
pop ds |
; correct positions in cache for existing items |
mov cx, 80h |
mov di, 8400h |
.correct: |
cmp [di+10], dx |
jbe @f |
sub [di+10], ax |
@@: |
add di, 12 |
loop .correct |
; some additional space is free now |
pop ax |
add [size_rest], ax |
sub [free_ptr], ax |
; add cache item to the list of free items |
mov dx, [bx] |
mov ax, [free_cache_item] |
mov [bx], ax |
mov [free_cache_item], bx |
mov bx, dx |
; current iteration done |
popa |
jmp .freeloop |
.sizeok: |
mov [cachelist.head], bx |
mov word [bx+2], cachelist |
; allocate new item in cache |
mov di, [free_cache_item] |
test di, di |
jz .nofree |
push word [di] |
pop [free_cache_item] |
jmp @f |
.nofree: |
mov di, [last_cache_item] |
add [last_cache_item], 12 |
@@: |
pop bx |
push si di |
; mov [di+4], eax ; start of folder |
scasd |
stosd |
push ax |
mov ax, [free_ptr] |
shl ax, 11-4 |
mov [di+10-8], ax |
mov es, ax |
pop ax |
add [free_ptr], cx |
sub [size_rest], cx |
; read folder data |
; first sector is already in memory, 0000:bx |
pusha |
mov cx, [bx+10] |
mov [di+8-8], cx ; folder size in bytes |
mov si, bx |
xor di, di |
mov cx, 0x1800 |
sub cx, si |
rep movsb |
pop ax |
push di |
popa |
; read rest of folder |
mov esi, dword [lb_per_sec] |
add eax, esi |
dec si |
not si |
and ax, si |
mov si, word [bx+10] |
mov bx, di |
pop di |
sub si, bx |
jbe @f |
mov [cur_limit], esi |
call read_many_bytes |
pop si |
jnc .scan |
jmp .readerr |
@@: |
pop si |
.scan: |
; now we have required cache item; append it to the end of list |
mov bx, [cachelist.tail] |
mov [cachelist.tail], di |
mov [di+2], bx |
mov word [di], cachelist |
mov [bx], di |
; scan for given filename |
mov es, [di+10] |
mov dx, [di+8] |
pop ds |
xor bx, bx |
call scan_for_filename_in_sector |
.scandone: |
push cs |
pop es |
mov bx, 2000h |
cmp bx, [es:cur_desc_end] |
jnz filefound |
j_notfound: |
jmp path_table_notfound |
filefound: |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
@@: |
mov cl, [es:bx+8] |
test al, al |
jz @f |
; parse next component of file name |
test cl, 2 ; directory? |
jz j_notfound |
mov eax, [es:bx] |
pop di |
jmp parse_dir |
@@: |
test cl, 2 ; directory? |
jnz j_notfound ; do not allow read directories as regular files |
; ok, now load the file |
pop di |
les bx, [di] |
call normalize |
movzx esi, word [di+4] ; esi = limit in 4K blocks |
shl esi, 12 ; esi = limit in bytes |
push cs |
pop ds |
mov [cur_limit], esi |
mov di, 2000h |
loadloop: |
and [cur_start], 0 |
.loadnew: |
mov esi, [cur_limit] |
mov eax, [cur_start] |
add esi, eax |
mov [overflow], 1 |
sub esi, [di+4] |
jb @f |
xor esi, esi |
dec [overflow] |
@@: |
add esi, [di+4] ; esi = number of bytes to read |
mov [cur_start], esi |
sub esi, eax |
jz .loadcontinue |
xor edx, edx |
div dword [lb_size] ; eax = number of logical blocks to skip, |
mov [first_byte], dx; [first_byte] = number of bytes to skip in 1st block |
cmp byte [di+10], 0 |
jnz .interleaved |
add eax, [di] |
; read esi bytes from logical block eax to buffer es:bx |
call read_many_bytes.with_first |
jc .readerr3 |
.loadcontinue: |
mov [cur_chunk], di |
add di, 11 |
cmp di, [cur_desc_end] |
jae @f |
cmp [cur_limit], 0 |
jnz loadloop |
@@: |
mov bx, [overflow] |
.calclen: |
; calculate length of file |
xor ax, ax |
xor dx, dx |
mov di, 2000h |
@@: |
add ax, [di+4] |
adc dx, [di+6] |
add di, 11 |
cmp di, [cur_desc_end] |
jb @b |
ret |
.interleaved: |
mov [cur_unit_limit], esi |
push esi |
; skip first blocks |
movzx ecx, byte [di+9] ; Unit Size |
movzx esi, byte [di+10] ; Interleave Gap |
add si, cx |
mov edx, [di] |
@@: |
sub eax, ecx |
jb @f |
add edx, esi |
jmp @b |
@@: |
add ecx, eax ; ecx = number of logical blocks to skip |
lea eax, [ecx+edx] ; eax = first logical block |
pop esi |
.interleaved_loop: |
; get number of bytes in current file unit |
push eax |
movzx eax, byte [di+9] |
sub ax, cx |
imul eax, dword [lb_size] |
cmp eax, esi |
ja .i2 |
.i1: |
xchg esi, eax |
.i2: |
pop eax |
sub [cur_unit_limit], esi |
push eax |
; read esi bytes from logical block eax to buffer es:bx |
call read_many_bytes.with_first |
pop eax |
jnc @f |
.readerr3: |
mov bx, 3 |
jmp .calclen |
@@: |
mov esi, [cur_unit_limit] |
test esi, esi |
jz .loadcontinue |
movzx ecx, byte [di+9] ; add Unit Size |
add cl, byte [di+10] ; add Interleave Gap |
adc ch, 0 |
add eax, ecx |
xor cx, cx |
mov [first_byte], cx |
jmp .interleaved_loop |
cx_to_sectors: |
add cx, 7FFh |
rcr cx, 1 |
shr cx, 10 |
ret |
is_last_component: |
; in: ds:si -> name |
; out: CF set <=> current component is not last (=> folder) |
push si |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
stc |
@@: |
pop si |
ret |
test_filename1: |
; in: ds:si -> filename, es:di -> path table item |
; out: CF set <=> no match |
pusha |
mov cl, [es:di] |
add di, 8 |
jmp test_filename2.start |
test_filename2: |
; in: ds:si -> filename, es:bx -> directory item |
; out: CF set <=> no match |
pusha |
mov cl, [es:bx+32] |
lea di, [bx+33] |
.start: |
mov ch, 0 |
@@: |
lodsb |
test al, al |
jz .test1 |
cmp al, '/' |
jz .test1 |
call toupper |
mov ah, al |
mov al, [es:di] |
call toupper |
inc di |
cmp al, ah |
loopz @b |
jnz .next1 |
; if we have reached this point: current name is done |
lodsb |
test al, al |
jz .ret |
cmp al, '/' |
jz .ret |
; if we have reached this point: current name is done, but input name continues |
; so they do not match |
jmp .next1 |
.test1: |
; if we have reached this point: input name is done, but current name continues |
; "filename.ext;version" in ISO-9660 represents file "filename.ext" |
; "filename." and "filename.;version" are also possible for "filename" |
cmp byte [es:di], '.' |
jnz @f |
inc di |
dec cx |
jz .ret |
@@: |
cmp byte [es:di], ';' |
jnz .next1 |
jmp .ret |
.next1: |
stc |
.ret: |
popa |
ret |
toupper: |
; in: al=symbol |
; out: al=symbol in uppercase |
cmp al, 'a' |
jb .ret |
cmp al, 'z' |
ja .ret |
sub al, 'a'-'A' |
.ret: |
ret |
scan_for_filename_in_sector: |
; in: ds:si->filename, es:bx->folder data, dx=limit |
; out: CF=0 if found |
push bx |
.loope: |
push bx |
.loop: |
cmp bx, dx |
jae .notfound |
cmp byte [es:bx], 0 |
jz .loopd |
test byte [es:bx+25], 4 ; ignore files with Associated bit |
jnz .next |
call test_filename2 |
jc .next |
push ds es di |
push es |
pop ds |
push cs |
pop es |
mov di, [es:cur_desc_end] |
movzx eax, byte [bx+1] |
add eax, [bx+2] |
stosd ; first logical block |
mov eax, [bx+10] |
stosd ; length |
mov al, [bx+25] |
stosb ; flags |
mov ax, [bx+26] |
stosw ; File Unit size, Interleave Gap size |
mov [es:cur_desc_end], di |
cmp di, 3000h |
pop di es ds |
jae .done |
test byte [es:bx+25], 80h |
jz .done |
.next: |
add bl, [es:bx] |
adc bh, 0 |
jmp .loop |
.loopd: |
mov ax, bx |
pop bx |
@@: |
add bx, [cs:lb_size] |
jz .done2 |
cmp bx, ax |
jb @b |
jmp .loope |
.notfound: |
stc |
.done: |
pop bx |
.done2: |
pop bx |
ret |
lb_to_sector: |
xor edx, edx |
div dword [lb_per_sec] |
ret |
load_phys_sector_for_lb_force: |
; in: eax = logical block, ds=0 |
; in: si=0 - accept 0 logical blocks, otherwise force read at least 1 |
; out: 0000:1000 = physical sector data; si -> logical block |
; out: eax = next physical sector |
; out: CF=1 if read error |
; destroys cx |
; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector |
call lb_to_sector |
or si, dx |
jnz @f |
mov si, 1800h |
jmp .done |
@@: |
mov si, 1000h |
imul dx, [lb_size] |
add si, dx |
mov cx, 1 |
push es bx |
push ds |
pop es |
mov bx, 1000h |
call read_sectors |
pop bx es |
inc eax |
.done: |
ret |
normalize: |
; in: es:bx = far pointer |
; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10) |
push ax bx |
mov ax, es |
shr bx, 4 |
add ax, bx |
mov es, ax |
pop bx ax |
and bx, 0x0F |
ret |
read_many_bytes: |
and [first_byte], 0 |
read_many_bytes.with_first: |
; read esi bytes from logical block dx:ax to buffer es:bx |
; out: CF=1 <=> disk error |
push di |
; load first physical sector |
push bx si |
mov si, [first_byte] |
call load_phys_sector_for_lb_force |
jnc @f |
pop si bx |
.ret: |
pop di |
ret |
@@: |
add si, [first_byte] |
mov ecx, 1800h |
sub cx, si |
mov ebx, esi |
pop bx |
sub ebx, ecx |
jnc @f |
add cx, bx |
xor ebx, ebx |
@@: |
pop di |
sub [cur_limit], ecx |
rep movsb |
mov esi, ebx |
mov bx, di |
call normalize |
; load other physical sectors |
; read esi bytes from physical sector eax to buffer es:bx |
test esi, esi |
jz .ret |
push esi |
add esi, 0x7FF |
and si, not 0x7FF |
cmp esi, [cur_limit] |
jbe .okplace |
.noplace: |
sub esi, 800h |
.okplace: |
shr esi, 11 ; si = number of sectors |
mov cx, si |
jz @f |
call read_sectors |
@@: |
pop esi |
jc .ret |
movzx ecx, cx |
add eax, ecx |
shl ecx, 11 |
sub [cur_limit], ecx |
sub esi, ecx |
jc .big |
jz .nopost |
push bx es |
push ds |
pop es |
mov bx, 1000h |
mov cx, 1 |
call read_sectors |
pop es di |
jc .ret2 |
mov cx, si |
mov si, 1000h |
sub word [cur_limit], cx |
sbb word [cur_limit+2], 0 |
rep movsb |
mov bx, di |
call normalize |
.nopost: |
clc |
.ret2: |
pop di |
ret |
.big: |
mov ax, es |
sub ax, 80h |
mov es, ax |
add bx, 800h |
add bx, si |
call normalize |
sub [cur_limit], esi |
jmp .nopost |
; Callback function for secondary loader |
callback: |
; in: ax = function number; only function 1 is defined for now |
dec ax |
jz callback_readfile |
dec ax |
jz callback_continueread |
stc ; unsupported function |
retf |
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 |
clc ; function is supported |
retf |
callback_continueread: |
; function 2: continue to 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) |
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error |
; out: dx:ax = file size |
les bx, [di] |
call normalize |
movzx esi, word [di+4] ; si = limit in 4K blocks |
shl esi, 12 ; bp:si = limit in bytes |
push cs |
pop ds |
mov [cur_limit], esi |
mov di, [cur_chunk] |
call loadloop.loadnew |
clc ; function is supported |
retf |
secondary_loader_info: |
dw 0, 0x1000 |
dw 0x30000 / 0x1000 |
db 'kernel.mnt',0 |
aKernelNotFound db 'Fatal error: cannot load the kernel',0 |
align 2 |
cachelist: |
.head dw cachelist |
.tail dw cachelist |
free_cache_item dw 0 |
last_cache_item dw 0x8400 |
use_path_table db 0 |
bootdrive db ? |
align 2 |
lb_size dw ? ; Logical Block size in bytes |
dw 0 ; to allow access dword [lb_size] |
lb_per_sec dw ? ; Logical Blocks per physical sector |
dw 0 ; to allow access dword [lb_per_sec] |
free_ptr dw ? ; first free block in cache (cache block = sector = 0x800 bytes) |
size_rest dw ? ; free space in cache (in blocks) |
cache_size dw ? |
cache_start dw ? |
pathtable_size dw ? |
pathtable_start dw ? |
root_location dd ? |
cur_desc_end dw ? |
cur_nocache_len dd ? |
cur_limit dd ? |
cur_unit_limit dd ? |
overflow dw ? |
cur_chunk dw ? |
first_byte dw ? |
cur_start dd ? |
times 83FCh-$ db 0 |
db 43h |
; just to make file 2048 bytes long :) |
db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' |
dw 0xAA55 ; this is not required for CD, but to be consistent... |
/kernel/trunk/bootloader/extended_primary_loader/cdfs/build.bat |
---|
0,0 → 1,2 |
@fasm -m 65535 bootsect.asm bootsect.bin |
@pause |
/kernel/trunk/bootloader/extended_primary_loader/cdfs/bootsect.txt |
---|
0,0 → 1,418 |
; 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. |
;***************************************************************************** |
Sector not found. N. N.N.N. N.N.N.N.N.N.N. N.N. N.N.N.N.N.N.? |
Áóòñåêòîð äëÿ çàãðóçêè ñ CD/DVD ñ ôàéëîâîé ñèñòåìîé ISO-9660. |
(ISO-9660 è å¸ ðàñøèðåíèÿ - ñòàíäàðò äëÿ CD; DVD ìîæåò èñïîëüçîâàòü |
ëèáî ISO-9660, ëèáî UDF.) |
===================================================================== |
Òðåáîâàíèÿ äëÿ ðàáîòû: |
1) Ñàì áóòñåêòîð è âñå èñïîëüçóåìûå ôàéëû äîëæíû áûòü ÷èòàáåëüíû. |
2) Ìèíèìàëüíûé ïðîöåññîð - 80386. |
3) Â ñèñòåìå äîëæíî áûòü êàê ìèíèìóì 452K ñâîáîäíîé áàçîâîé ïàìÿòè. |
===================================================================== |
Äîêóìåíòàöèÿ â òåìó (ññûëêè ïðîâåðÿëèñü íà âàëèäíîñòü 14.09.2008): |
ñòàíäàðò ISO-9660: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf |
ñòàíäàðò çàãðóçî÷íîãî CD: http://www.phoenix.com/NR/rdonlyres/98D3219C-9CC9-4DF5-B496-A286D893E36A/0/specscdrom.pdf |
îôèöèàëüíàÿ ñïåöèôèêàöèÿ ðàñøèðåíèÿ 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 |
===================================================================== |
Ñõåìà èñïîëüçóåìîé ïàìÿòè: |
1000-1800 âðåìåííûé áóôåð äëÿ ÷òåíèÿ îäèíî÷íûõ ñåêòîðîâ |
...-7C00 ñòåê |
7C00-8400 êîä áóòñåêòîðà |
8400-8A00 èíôîðìàöèÿ î êýøå äëÿ ïàïîê: ìàññèâ âõîäîâ ñëåäóþùåãî |
ôîðìàòà: |
dw ñëåäóþùèé ýëåìåíò â L2-ñïèñêå çàêýøèðîâàííûõ ïàïîê, |
óïîðÿäî÷åííîì ïî âðåìåíè èñïîëüçîâàíèÿ |
(ãîëîâà ñïèñêà - ñàìûé ñòàðûé); |
dw ïðåäûäóùèé ýëåìåíò â òîì æå ñïèñêå; |
dd ïåðâûé ñåêòîð ïàïêè; |
dw ðàçìåð ïàïêè â áàéòàõ; |
dw ñåãìåíò êýøà |
60000-... ñîäåðæèìîå Path Table, åñëè îíà èñïîëüçóåòñÿ |
+ êýø äëÿ ïàïîê; |
òî÷íûé ðàçìåð îïðåäåëÿåòñÿ ðàçìåðîì äîñòóïíîé |
ôèçè÷åñêîé ïàìÿòè - êàê ïðàâèëî, íåïîñðåäñòâåííî |
ïåðåä A0000 ðàçìåùàåòñÿ EBDA, Extended BIOS Data Area |
===================================================================== |
Îñíîâíîé ïðîöåññ çàãðóçêè. |
Òî÷êà âõîäà (start): ïîëó÷àåò óïðàâëåíèå îò BIOS ïðè çàãðóçêå, ïðè ýòîì |
dl ñîäåðæèò èäåíòèôèêàòîð äèñêà, ñ êîòîðîãî èä¸ò çàãðóçêà |
1. Ïðè ïåðåäà÷å óïðàâëåíèÿ çàãðóçî÷íîìó êîäó â ñëó÷àå CD/DVD ïàðà cs:ip |
ðàâíà íå 0:7C00, à íà 07C0:0000. Ïîýòîìó ñíà÷àëà çàãðóç÷èê äåëàåò |
äàëüíèé ïðûæîê íà ñàìîãî ñåáÿ ñ öåëüþ ïîëó÷èòü cs=0 (â íåêîòîðûõ |
ìåñòàõ èñïîëüçóåòñÿ àäðåñàöèÿ ïåðåìåííûõ çàãðóç÷èêà ÷åðåç cs, ïîñêîëüêó |
è ds, è es ìîãóò áûòü çàíÿòû ïîä äðóãèå ñåãìåíòû). |
2. Íàñòðàèâàåò ñòåê ss:sp = 0:7C00 (íåïîñðåäñòâåííî ïåðåä îñíîâíûì êîäîì) |
è ñåãìåíòíûå ðåãèñòðû ds=es=0. Ôîðñèðóåò ñáðîøåííûé ôëàã íàïðàâëåíèÿ |
è ðàçðåø¸ííûå ïðåðûâàíèÿ. Ñîõðàíÿåò èäåíòèôèêàòîð çàãðóçî÷íîãî äèñêà |
â ñïåöèàëüíóþ ïåðåìåííóþ. |
3. Ïðîâåðÿåò ïîääåðæêó LBA. Äëÿ CD/DVD íîñèòåëÿ BIOS îáÿçàíà ïðåäîñòàâëÿòü |
LBA-ôóíêöèè. |
4. Èùåò îïèñàòåëü òîìà CD (Primary Volume Descriptor, PVD): ïî ñòàíäàðòó |
ISO9660 ñî ñìåùåíèÿ 10h íà÷èíàåòñÿ öåïî÷êà îïèñàòåëåé òîìà, |
çàâåðøàþùàÿñÿ ñïåöèàëüíûì îïèñàòåëåì (Volume Descriptor Set |
Terminator). Êîä ïî î÷åðåäè ñ÷èòûâàåò âñå ñåêòîðà, ïîêà íå íàòêí¸òñÿ |
ëèáî íà èñêîìûé îïèñàòåëü, ëèáî íà òåðìèíàòîð. Âî âòîðîì ñëó÷àå |
âûäà¸òñÿ ñîîòâåòñòâóþùåå ñîîáùåíèå, è çàãðóçêà ïðåêðàùàåòñÿ. |
Âîîáùå ãîâîðÿ, â ñëó÷àå ìóëüòèñåññèîííûõ CD îñíîâíîé êàòàëîã ñîäåðæèìîãî CD |
ðàñïîëàãàåòñÿ â ïîñëåäíåé ñåññèè. È ñïåöèôèêàöèÿ ElTorito çàãðóçî÷íîãî |
CD îïåðèðóåò òàêæå ñ ïîñëåäíåé ñåññèåé. Îäíàêî íà ïðàêòèêå îêàçûâàåòñÿ, |
÷òî: âî-ïåðâûõ, ðåàëüíûå BIOSû íå ïîíèìàþò ìóëüòèñåññèîííûõ CD è |
âñåãäà èñïîëüçóþò ïåðâóþ ñåññèþ; âî-âòîðûõ, BIOSîâñêèé int 13h ïðîñòî |
íå ïîçâîëÿåò ïîëó÷èòü èíôîðìàöèþ î ïîñëåäíåé ñåññèè.  ñâÿçè ñ ýòèì |
çàãðóç÷èê òàêæå èñïîëüçóåò ïåðâóþ ñåññèþ. (Â-òðåòüèõ, â îäíîé èç BIOS |
îáíàðóæèëàñü çàãîòîâêà, êîòîðàÿ â ñëó÷àå çàïðîñà ñåêòîðà 10h, â êîòîðîì |
âî âñåõ íîðìàëüíûõ ñëó÷àÿõ è ðàñïîëàãàåòñÿ PVD, ïåðåíàïðàâëÿåò åãî |
íà ñåêòîð 10h+(íà÷àëî ñåññèè). Åñëè áû ýòîò BIOS åù¸ è ãðóçèëñÿ ñ |
ïîñëåäíåé ñåññèè, òî áëàãîäàðÿ çàãîòîâêå çàãðóç÷èê áåç âñÿêèõ |
ìîäèôèêàöèé òàêæå ÷èòàë áû ïîñëåäíþþ ñåññèþ.) |
5. (ìåòêà pvd_found) Ñ÷èòûâàåò èç PVD íåêîòîðóþ èíôîðìàöèþ î òîìå âî |
âíóòðåííèå ïåðåìåííûå: ðàçìåð ëîãè÷åñêîãî áëîêà (ñîãëàñíî ñïåöèôèêàöèè, |
äîëæåí áûòü ñòåïåíüþ äâîéêè îò 512 äî ðàçìåðà ëîãè÷åñêîãî ñåêòîðà, |
ðàâíîãî 2048 äëÿ CD è DVD); ïîëîæåíèå íà äèñêå êîðíåâîé ïàïêè; |
âû÷èñëÿåò ÷èñëî áëîêîâ â ñåêòîðå (èç ïðåäûäóùåãî ïðèìå÷àíèÿ ñëåäóåò, |
÷òî îíî âñåãäà öåëîå è ñàìî ÿâëÿåòñÿ ñòåïåíüþ äâîéêè). |
6. Ïîëó÷àåò ðàçìåð áàçîâîé ïàìÿòè âûçîâîì int 12h; íà åãî îñíîâå âû÷èñëÿåò |
ðàçìåð ïðîñòðàíñòâà, êîòîðîå ìîæåò èñïîëüçîâàòü çàãðóç÷èê (îò |
àäðåñà 6000:0000 äî êîíöà äîñòóïíîé ïàìÿòè). |
7. Çàãðóæàåò òàáëèöó ïóòåé CD (Path Table) - îáëàñòü äàííûõ, êîòîðàÿ ñîäåðæèò |
áàçîâóþ èíôîðìàöèþ îáî âñåõ ïàïêàõ íà äèñêå. Åñëè òàáëèöà ñëèøêîì |
âåëèêà (áîëüøå 62K èëè áîëüøå ïîëîâèíû äîñòóïíîé ïàìÿòè), òî îíà |
èãíîðèðóåòñÿ. Åñëè òàáëèöà ïóòåé íåäîñòóïíà, òî çàïðîñ òèïà |
dir1/dir2/dir3/file ïðèâåä¸ò ê ïîñëåäîâàòåëüíîìó ðàçáîðó êîðíåâîé |
ïàïêè è ïàïîê dir1,dir2,dir3; åñëè äîñòóïíà, òî äîñòàòî÷íî ðàçîáðàòü |
ñàìó òàáëèöó ïóòåé (ãäå çàïèñàíî ïîëîæåíèå ïàïêè dir1/dir2/dir3) |
è ïàïêó dir3. Åñëè òàáëèöà çàãðóæåíà, òî ñîîòâåòñòâåííî óìåíüøàåòñÿ |
îáú¸ì îñòàâøåéñÿ äîñòóïíîé ïàìÿòè è óâåëè÷èâàåòñÿ óêàçàòåëü íà |
ñâîáîäíóþ îáëàñòü. |
8. Çàïîìèíàåò îáùèé ðàçìåð è íà÷àëî êýøà äëÿ ïàïîê (âñÿ îñòàâøàÿñÿ ïîñëå ï.7 |
äîñòóïíàÿ ïàìÿòü îòâîäèòñÿ ïîä ýòîò êýø). |
9. Âûäà¸ò çàïðîñ íà ÷òåíèå ôàéëà âòîðè÷íîãî çàãðóç÷èêà kord/loader. Ïðè îøèáêå |
ïå÷àòàåò ñîîòâåòñòâóþùåå ñîîáùåíèå è ïðåêðàùàåò çàãðóçêó ñ CD. |
10. Óñòàíàâëèâàåò ðåãèñòðû äëÿ âòîðè÷íîãî çàãðóç÷èêà: al='c' èäåíòèôèöèðóåò |
òèï óñòðîéñòâà - CD/DVD; ah=BIOS-èäåíòèôèêàòîð äèñêà; bx='is' |
èäåíòèôèöèðóåò ôàéëîâóþ ñèñòåìó ISO-9660; ds:si óêàçûâàåò íà |
callback-ôóíêöèþ, êîòîðóþ ìîæåò âûçûâàòü âòîðè÷íûé çàãðóç÷èê. |
11. Ïåðåäà¸ò óïðàâëåíèå âòîðè÷íîìó çàãðóç÷èêó, ñîâåðøàÿ äàëüíèé ïðûæîê |
íà àäðåñ, êóäà kord/loader áûë çàãðóæåí. |
Ôóíêöèÿ îáðàòíîãî âûçîâà äëÿ âòîðè÷íîãî çàãðóç÷èêà (callback): |
ïðåäîñòàâëÿåò âîçìîæíîñòü ÷òåíèÿ ôàéëà. |
Âõîä è âûõîä îïèñàíû â ñïåöèôèêàöèè íà çàãðóç÷èê. |
Ïåðåíàïðàâëÿåò çàïðîñ ñîîòâåòñòâóþùåé ëîêàëüíîé ïðîöåäóðå (load_file ïðè |
ïåðâîì çàïðîñå íà çàãðóçêó ôàéëà, loadloop.loadnew ïðè ïîñëåäóþùèõ |
çàïðîñàõ íà ïðîäîëæåíèå çàãðóçêè ôàéëà). |
Âñïîìîãàòåëüíûå ïðîöåäóðû. |
Êîä îáðàáîòêè îøèáîê (err): |
1. Âûâîäèò ñòðîêó ñ ñîîáùåíèåì îá îøèáêå. |
2. Âûâîäèò ñòðîêó "Press any key...". |
3. Æä¸ò íàæàòèÿ any key. |
4. Âûçûâàåò int 18h, äàâàÿ øàíñ BIOSó ïîïûòàòüñÿ çàãðóçèòüñÿ îòêóäà-íèáóäü åù¸. |
5. Äëÿ ïîäñòðàõîâêè çàöèêëèâàåòñÿ. |
Ïðîöåäóðà ÷òåíèÿ ñåêòîðîâ (read_sectors): |
íà âõîäå äîëæíî áûòü óñòàíîâëåíî: |
es:bx = óêàçàòåëü íà íà÷àëî áóôåðà, êóäà áóäóò ïðî÷èòàíû äàííûå |
eax = ñòàðòîâûé ñåêòîð |
cx = ÷èñëî ñåêòîðîâ |
íà âûõîäå: |
es:bx óêàçûâàåò íà êîíåö áóôåðà, â êîòîðûé áûëè ïðî÷èòàíû äàííûå |
åñëè ïðîèçîøëà îøèáêà ÷òåíèÿ, ôëàã CF óñòàíîâëåí |
1.  öèêëå (øàãè 2-4) ÷èòàåò ñåêòîðû, ñëåäèò çà òåì, ÷òîáû íà êàæäîé èòåðàöèè |
÷èñëî ÷èòàåìûõ ñåêòîðîâ íå ïðåâîñõîäèëî 7Fh (òðåáîâàíèå ñïåöèôèêàöèè |
EDD BIOS). |
2. Åñëè ÷èñëî ñåêòîðîâ äëÿ ÷òåíèÿ áîëüøå 7Fh, óìåíüøàåò åãî (äëÿ òåêóùåé |
èòåðàöèè) äî 7Fh. |
3. Ôîðìèðóåò â ñòåêå ïàêåò äëÿ int 13h (êëàä¸ò âñå íóæíûå äàííûå êîìàíäàìè |
push, ïðè÷¸ì â îáðàòíîì ïîðÿäêå: ñòåê - ñòðóêòóðà LIFO, è äàííûå â |
ñòåêå õðàíÿòñÿ â îáðàòíîì ïîðÿäêå ïî îòíîøåíèþ ê òîìó, êàê èõ òóäà |
êëàëè). |
4. Âûçûâàåò BIOS. Åñëè BIOS ðàïîðòóåò îá îøèáêå, î÷èùàåò ñòåê, |
óñòàíàâëèâàåò CF=1 è âûõîäèò èç ïðîöåäóðû. |
Î÷èùàåò ñòåê îò ïàêåòà, ñôîðìèðîâàííîãî íà ïðåäûäóùåì øàãå. |
5.  ñîîòâåòñòâèè ñ ÷èñëîì ïðî÷èòàííûõ íà òåêóùåé èòåðàöèè ñåêòîðîâ |
êîððåêòèðóåò òåêóùèé ñåêòîð, ÷èñëî îñòàâøèõñÿ ñåêòîðîâ è óêàçàòåëü íà |
áóôåð (â ïàðå es:bx êîððåêòèðóåòñÿ es). Åñëè âñ¸ ïðî÷èòàíî, çàêàí÷èâàåò |
ðàáîòó, èíà÷å âîçâðàùàåòñÿ íà øàã 2. |
Ïðîöåäóðà âûâîäà íà ýêðàí ASCIIZ-ñòðîêè (out_string): |
íà âõîäå: ds:si -> ñòðîêà |
 öèêëå, ïîêà íå äîñòèãíóò çàâåðøàþùèé íîëü, âûçûâàåò ôóíêöèþ int 10h/ah=0Eh. |
Ïðîöåäóðà çàãðóçêè ôàéëà (load_file): |
íà âõîäå: |
ds:di = óêàçàòåëü íà èíôîðìàöèîííóþ ñòðóêòóðó, îïèñàííóþ â ñïåöèôèêàöèè |
íà çàãðóç÷èê, à òàêæå â êîììåíòàðèÿõ ê êîäó |
íà âûõîäå: |
bx = ñòàòóñ: 0=óñïåõ, 1=ôàéë ñëèøêîì áîëüøîé, ïðî÷èòàíà òîëüêî ÷àñòü, |
2=ôàéë íå íàéäåí, 3=îøèáêà ÷òåíèÿ |
dx:ax = ðàçìåð ôàéëà, 0xFFFFFFFF, åñëè ôàéë íå íàéäåí |
1. Åñëè ïîäãîòîâèòåëüíûé êîä çàãðóçèë òàáëèöó ïóòåé, òî èùåò ïàïêó â òàáëèöå, |
èíà÷å ïåðåõîäèò ñðàçó ê øàãó 4, óñòàíîâèâ eax = íà÷àëüíûé áëîê |
êîðíåâîé ïàïêè. |
2. Óñòàíàâëèâàåò es:di íà íà÷àëî òàáëèöû ïóòåé. Îãðàíè÷åíèå íà ðàçìåð |
ãàðàíòèðóåò, ÷òî âñÿ òàáëèöà ïîìåùàåòñÿ â ñåãìåíòå 6000h. |
Èíèöèàëèçèðóåò dx (â êîòîðîì áóäåò õðàíèòñÿ íîìåð òåêóùåãî âõîäà â |
òàáëèöå, ñ÷èòàÿ ñ 1), cx (ðàçìåð îñòàâøåãîñÿ ó÷àñòêà òàáëèöû), |
bx (íîìåð âõîäà, ñîîòâåòñòâóþùåãî ðîäèòåëüñêîé ïàïêå äëÿ òåêóùåãî |
ðàññìàòðèâàåìîãî ó÷àñòêà ïóòè). |
3. Â öèêëå èùåò âõîä ñ íóæíûì ðîäèòåëüñêèì ýëåìåíòîì è íóæíûì èìåíåì. Ýëåìåíòû |
òàáëèöû ïóòåé óïîðÿäî÷åíû (ïîäðîáíî î ïîðÿäêå íàïèñàíî â ñïåöèôèêàöèè), |
òàê ÷òî åñëè ðîäèòåëüñêèé ýëåìåíò äëÿ î÷åðåäíîãî âõîäà áîëüøå íóæíîãî, |
òî íóæíîãî âõîäà â òàáëèöå íåò ñîâñåì, è â ýòîì ñëó÷àå ïðîèñõîäèò |
âûõîä èç ïðîöåäóðû ñ bx=2, ax=dx=0xFFFF. Åñëè îáíàðóæèëñÿ ýëåìåíò, |
ñîîòâåòñòâóþùèé î÷åðåäíîé ïàïêå â çàïðîøåííîì ïóòè, òî íà ðàññìîòðåíèå |
âûíîñèòñÿ ñëåäóþùàÿ êîìïîíåíòà ïóòè. Åñëè ýòà êîìïîíåíòà ïîñëåäíÿÿ, |
òî îñòàëîñü íàéòè ôàéë â ïàïêå, è êîä ïåðåõîäèò ê ïóíêòó 4, |
óñòàíîâèâ eax = íà÷àëüíûé áëîê ýòîé ïàïêè. Åñëè æå íåò, òî ýòà |
êîìïîíåíòà äîëæíà çàäàâàòü èìÿ ïàïêè, è êîä âîçâðàùàåòñÿ ê ïóíêòó 3, |
ñêîððåêòèðîâàâ óêàçàòåëü íà èìÿ ds:si è íîìåð ðîäèòåëüñêîãî âõîäà bx. |
4. (parse_dir) Íà ýòîì øàãå çàäàíû íà÷àëüíûé ëîãè÷åñêèé áëîê ïàïêè â eax |
è óêàçàòåëü íà èìÿ ôàéëà îòíîñèòåëüíî ýòîé ïàïêè â ds:si. Åñëè |
ïàïêó èñêàëè ïî òàáëèöå ïóòåé, òî èìÿ ôàéëà óæå íå ñîäåðæèò ïîäïàïîê; |
åñëè æå íåò, òî ïîäïàïêè âïîëíå âîçìîæíû. |
5. Ôàéëû â ISO-9660 ìîãóò ñîñòîÿòü èç íåñêîëüêèõ êóñêîâ (File Section), êàæäûé |
èç êîòîðûõ çàäà¸òñÿ îòäåëüíûì âõîäîì â ïàïêå. Èíôîðìàöèÿ îáî âñåõ |
òàêèõ êóñêàõ ïðè ïðîñìîòðå ïàïêè çàïîìèíàåòñÿ â îáëàñòè, íà÷èíàþùåéñÿ |
ñ àäðåñà 0000:2000. Ïåðåìåííàÿ cur_desc_end ñîäåðæèò óêàçàòåëü íà |
êîíåö ýòîé îáëàñòè, îí æå óêàçàòåëü, êóäà áóäåò ïîìåùåíà èíôîðìàöèÿ |
ïðè îáíàðóæåíèè ñëåäóþùåãî âõîäà. (Ïàïêè, ñîãëàñíî ñïåöèôèêàöèè, |
äîëæíû çàäàâàòüñÿ îäíèì êóñêîì.) |
6. Êîä ñíà÷àëà èùåò çàïðîøåííóþ ïàïêó â êýøå ïàïîê. |
7. (parse_dir.found) Åñëè ïàïêà óæå åñòü â êýøå, òî îíà óäàëÿåòñÿ èç ñïèñêà, |
îòñîðòèðîâàííîãî ïî äàâíîñòè ïîñëåäíåãî îáðàùåíèÿ è êîä ïåðåõîäèò ê |
ï.15. (Ñëåäóþùèì äåéñòâèåì ñòàíåò äîáàâëåíèå ïàïêè â êîíåö ñïèñêà.) |
8. (parse_dir.notfound) Åñëè æå ïàïêè íåò â êýøå, òî å¸ ïðèä¸òñÿ çàãðóæàòü |
ñ äèñêà. Ñíà÷àëà çàãðóæàåòñÿ ïåðâûé ñåêòîð (ôèçè÷åñêèé ñåêòîð, |
ñîäåðæàùèé ïåðâûé ëîãè÷åñêèé áëîê). Ïðè îøèáêå ââîäà/âûâîäà |
ïðîèñõîäèò íåìåäëåííûé âûõîä èç ïðîöåäóðû ñ bx=3, dx=ax=0xFFFF. |
Ïåðâûé ýëåìåíò ïàïêè ñîäåðæèò èíôîðìàöèþ î ñàìîé ýòîé ïàïêå, êîíêðåòíî |
çàãðóç÷èê èíòåðåñóåòñÿ å¸ ðàçìåðîì. |
9. Åñëè ðàçìåð ïàïêè ñëèøêîì áîëüøîé (áîëüøå èëè ðàâåí 64K ëèáî áîëüøå ïîëîâèíû |
îáùåãî ðàçìåðà êýøà), òî êýøèðîâàòüñÿ îíà íå áóäåò.  ýòîì ñëó÷àå êîä |
ñ÷èòûâàåò ïàïêó ïîñåêòîðíî âî âðåìåííûé áóôåð (0000:1000) è ïîñåêòîðíî |
ñêàíèðóåò íà íàëè÷èå çàïðîøåííîãî èìåíè, ïîêà íå íàéä¸ò òàêîãî èìåíè |
èëè ïîêà íå êîí÷àòñÿ äàííûå. (Öèêë íà÷èíàåòñÿ ñî ñêàíèðîâàíèÿ, |
ïîñêîëüêó ïåðâàÿ ÷àñòü äàííûõ óæå ïðî÷èòàíà.)  êîíöå êîä ïåðåõîäèò |
ê ï.17. |
10. (parse_dir.yescache) Åñëè ïðèíÿòî ðåøåíèå î êýøèðîâàíèè ïàïêè, òî íóæíî |
îáåñïå÷èòü äîñòàòî÷íîå êîëè÷åñòâî ñâîáîäíîãî ìåñòà. Äëÿ ýòîãî ìîæåò |
ïîíàäîáèòüñÿ âûêèíóòü êàêîå-òî êîëè÷åñòâî ñòàðûõ äàííûõ (öèêë |
parse_dir.freeloop). Íî åñëè ïðîñòî âûêèäûâàòü, òî, âîîáùå ãîâîðÿ, |
ñâîáîäíîå ïðîñòðàíñòâî îêàæåòñÿ ðàçîðâàííûì íà íåñêîëüêî ôðàãìåíòîâ. |
Ïîýòîìó ïðè âûêèäûâàíèè êàêîé-òî ïàïêè èç êýøà çàãðóç÷èê ïåðåìåùàåò |
âñå ñëåäóþùèå çà íåé äàííûå íàçàä ïî ïàìÿòè è ñîîòâåòñòâåííî |
êîððåêòèðóåò èíôîðìàöèþ î ìåñòîíàõîæäåíèè äàííûõ â èíôîðìàöèè î êýøå. |
Ïðè ýòîì íîâîå ïðîñòðàíñòâî âñåãäà äîáàâëÿåòñÿ â êîíåö äîñòóïíîé |
ïàìÿòè. Öèêë âûêèäûâàíèÿ ïðîäîëæàåòñÿ, ïîêà íå îñâîáîäèòñÿ ìåñòî, |
äîñòàòî÷íîå äëÿ õðàíåíèÿ ïàïêè. Èç-çà îãðàíè÷åíèé íà ðàçìåð êýøèðóåìûõ |
ïàïîê â êîíöå êîíöîâ ìåñòî íàéä¸òñÿ. |
11. Âûäåëÿåòñÿ íîâûé ýëåìåíò êýøà. Âñå óäàë¸ííûå íà øàãå 10 ýëåìåíòû |
îðãàíèçóþòñÿ â åäèíûé ñïèñîê ñâîáîäíûõ ýëåìåíòîâ; åñëè îí íåïóñò, |
òî î÷åðåäíîé ýëåìåíò áåð¸òñÿ èç ýòîãî ñïèñêà; åñëè æå ïóñò, òî |
áåð¸òñÿ ñîâñåì íîâûé ýëåìåíò èç îáëàñòè ïàìÿòè, ïðåäíàçíà÷åííîé äëÿ |
ýëåìåíòîâ êýøà. |
12.  íîâîì ýëåìåíòå çàïîëíÿþòñÿ ïîëÿ íà÷àëüíîãî áëîêà, ñåãìåíòà ñ äàííûìè, |
ðàçìåðà â áàéòàõ. |
13. Óæå ïðî÷èòàííûå äàííûå ïåðâîãî ôèçè÷åñêîãî ñåêòîðà ïåðåñûëàþòñÿ íà |
çàêîííîå ìåñòî â êýøå. |
14. Åñëè âñå äàííûå íå èñ÷åðïûâàþòñÿ ïåðâûì ñåêòîðîì, òî äîãðóæàþòñÿ îñòàâøèåñÿ |
äàííûå ñ äèñêà. Ïðè îøèáêå ÷òåíèÿ, êàê è ðàíüøå, ïðîèñõîäèò âûõîä èç |
ïðîöåäóðû ñ bx=3, ax=dx=0xFFFF. |
15. (parse_dir.scan) Íîâûé ýëåìåíò äîáàâëÿåòñÿ â êîíåö ñïèñêà âñåõ ýëåìåíòîâ |
êýøà. |
16. Çàãðóç÷èê èùåò çàïðîøåííîå èìÿ â çàãðóæåííûõ äàííûõ ïàïêè. |
(Èç-çà îãðàíè÷åíèé íà ðàçìåð êýøèðóåìîé ïàïêè âñå äàííûå ðàñïîëàãàþòñÿ |
â îäíîì ñåãìåíòå.) |
17. (parse_dir.scandone) Åñëè â ïðîöåññå ñêàíèðîâàíèÿ ïàïêè íå áûëî íàéäåíî |
íèêàêèõ êóñêîâ ôàéëà, òî cur_desc_end òàêîé æå, êàêèì áûë âíà÷àëå. |
 ýòîì ñëó÷àå ïðîöåäóðà ðàïîðòóåò î íåíàéäåííîì ôàéëå è âûõîäèò. |
18. (filefound) Ïðîïóñêàåò òåêóùóþ êîìïîíåíòó èìåíè. Åñëè îíà áûëà íå ïîñëåäíåé |
(òî åñòü ïîäïàïêîé, â êîòîðîé íóæíî ïðîèçâîäèòü äàëüíåéøèé ïîèñê), |
òî êîä ïðîâåðÿåò, ÷òî íàéäåííûé âõîä - äåéñòâèòåëüíî ïîäïàïêà, |
óñòàíàâëèâàåò íîâûé ñòàðòîâûé áëîê è âîçâðàùàåòñÿ ê ï.4. |
Åñëè æå ïîñëåäíåé, òî êîä ïðîâåðÿåò, ÷òî íàéäåííûé âõîä - ðåãóëÿðíûé |
ôàéë è íà÷èíàåò çàãðóçêó ôàéëà. |
19. Íîðìàëèçóåò óêàçàòåëü, ïî êîòîðîìó òðåáóåòñÿ ïðî÷èòàòü ôàéë. Ïîä |
íîðìàëèçàöèåé ïîíèìàåòñÿ ïðåîáðàçîâàíèå òèïà |
1234:FC08 -> (1234+0FC0):0008, êîòîðîå íå ìåíÿåò ñóììàðíîãî àäðåñà, |
íî ãàðàíòèðóåò îòñóòñòâèå ïåðåïîëíåíèé: â ïðèâåä¸ííîì ïðèìåðå ïîïûòêà |
ïåðåñëàòü 400h áàéò ïî rep movsb ïðèâåä¸ò ê òîìó, ÷òî ïîñëåäíèå 8 |
áàéò çàïèøóòñÿ íå â íóæíîå ìåñòî, à íà 64K ðàíüøå. Äàëåå íîðìàëèçàöèÿ |
áóäåò ïðîèçâîäèòüñÿ ïîñëå êàæäîé ïåðåñûëêè. Â cur_limit ïîìåùàåò |
ïðåäåëüíûé ðàçìåð äëÿ ÷òåíèÿ â áàéòàõ. |
20. (loadloop) Â öèêëå ïî íàéäåííûì ôðàãìåíòàì ôàéëà çàãðóæàåò ýòè ôðàãìåíòû |
(ïóíêòû 21-27). |
21. Îáíóëÿåò ïåðåìåííóþ [cur_start], èìåþùóþ ñìûñë ÷èñëà áàéò, êîòîðîå |
íóæíî ïðîïóñòèòü ñ íà÷àëà ôðàãìåíòà. |
22. (loadloop.loadnew) Íà ýòó ìåòêó óïðàâëåíèå ìîæåò ïîïàñòü ëèáî ñ ïðåäûäóùåãî |
øàãà, ëèáî íàïðÿìóþ èç callback-ïðîöåäóðû ïðè çàïðîñå íà ïðîäîëæåíèå |
÷òåíèÿ. Äëÿ ýòîãî è íóæíà âûøåóïîìÿíóòàÿ ïåðåìåííàÿ [cur_start] - |
ïðè ïðîäîëæåíèè ÷òåíèÿ, ïðåðâàâøåãîñÿ èç-çà êîíöà áóôåðà ïîñåðåäèíå |
ôðàãìåíòà, òàì áóäåò çàïèñàíî ñîîòâåòñòâóþùåå çíà÷åíèå. |
23. Îïðåäåëÿåò òåêóùóþ äëèíó (õðàíèòñÿ â esi) êàê ìèíèìóì èç äëèíû ôðàãìåíòà |
è ìàêñèìàëüíîé äëèíû îñòàòêà. Åñëè âòîðîå ñòðîãî ìåíüøå, òî |
çàïîìèíàåò, ÷òî ôàéë ñëèøêîì áîëüøîé è ïðî÷èòàí òîëüêî ÷àñòè÷íî. |
Îïðåäåëÿåò íîâîå çíà÷åíèå ÷èñëà ïðî÷èòàííûõ áàéò âî ôðàãìåíòå |
äëÿ âîçìîæíûõ áóäóùèõ âûçîâîâ [cur_start]. |
24. Ïåðåâîäèò ïðîïóñêàåìîå ÷èñëî áàéò â ÷èñëî ëîãè÷åñêèõ áëîêîâ è áàéò |
â ïåðâîì áëîêå, ïîñëåäíåå ÷èñëî çàïèñûâàåò â ïåðåìåííóþ [first_byte], |
îòêóäà å¸ ïîçäíåå äîñòàíåò read_many_bytes.with_first. |
25. Åñëè ôðàãìåíò çàïèñàí â îáû÷íîì ðåæèìå (non-interleaved mode), òî êîä |
îïðåäåëÿåò íà÷àëüíûé áëîê ôðàãìåíòà è âûçûâàåò âñïîìîãàòåëüíóþ ôóíêöèþ |
÷òåíèÿ áëîêîâ. Ïðè îøèáêå ÷òåíèÿ óñòàíàâëèâàåò bx=3 (êîä îøèáêè ÷òåíèÿ) |
è âûõîäèò èç öèêëà ê ï.28. |
26. Åñëè ôðàãìåíò çàïèñàí â ÷åðåäóåìîì ðåæèìå (interleaved mode), òî ñíà÷àëà |
êîä ïðîïóñêàåò íóæíîå êîëè÷åñòâî íåïðåðûâíûõ ÷àñòåé, à ïîòîì |
â öèêëå çàãðóæàåò íåïðåðûâíûå ÷àñòè ñ ïîìîùüþ òîé æå ôóíêöèè, |
â ïðîìåæóòêàõ ìåæäó ÷àñòÿìè óâåëè÷èâàÿ íîìåð íà÷àëüíîãî áëîêà. |
Ïîêà íå êîí÷èòñÿ ôðàãìåíò èëè ïîêà íå íàáåð¸òñÿ çàïðîøåííîå ÷èñëî áàéò. |
Ïðè îøèáêå ÷òåíèÿ äåëàåò òî æå ñàìîå, ÷òî è â ïðåäûäóùåì ñëó÷àå. |
27. (loadloop.loadcontinue) Åñëè ôðàãìåíòû åù¸ íå êîí÷èëèñü è ïðåäåëüíûé ðàçìåð |
åù¸ íå äîñòèãíóò, ïåðåõîäèò ê ñëåäóþùåìó ôðàãìåíòó è ï.20. Â ïðîòèâíîì |
ñëó÷àå óñòàíàâëèâàåò bx=0 ëèáî bx=1 â çàâèñèìîñòè îò òîãî, áûëî ëè |
ïåðåïîëíåíèå â ï.23. |
28. (loadloop.calclen) Ïîäñ÷èòûâàåò îáùóþ äëèíó ôàéëà, ñóììèðóÿ äëèíû âñåõ |
ôðàãìåíòîâ. |
Ïðîöåäóðà ïðîâåðêè, ÿâëÿåòñÿ ëè òåêóùàÿ êîìïîíåíòà èìåíè ôàéëà ïîñëåäíåé |
(is_last_component): |
íà âõîäå: ds:si = óêàçàòåëü íà èìÿ |
íà âûõîäå: ôëàã CF óñòàíîâëåí, åñëè åñòü ïîñëåäóþùèå êîìïîíåíòû |
 öèêëå çàãðóæàåò ñèìâîëû èìåíè â ïîèñêàõ íóëåâîãî è '/'; åñëè íàø¸ëñÿ ïåðâûé, |
òî âûõîäèò (ïðè ýòîì CF=0); åñëè íàø¸ëñÿ âòîðîé, òî óñòàíàâëèâàåò CF |
è âûõîäèò. |
Ïðîöåäóðû ïðîâåðêè íà ñîâïàäåíèå òåêóùåé êîìïîíåíòû èìåíè ôàéëà ñ èìåíåì |
òåêóùåãî ýëåìåíòà (test_filename1 äëÿ òàáëèöû ïóòåé, test_filename2 äëÿ ïàïêè): |
íà âõîäå: ds:si = óêàçàòåëü íà èìÿ, es:di = óêàçàòåëü íà ýëåìåíò |
òàáëèöû ïóòåé äëÿ test_filename1, ïàïêè äëÿ test_filename2 |
íà âûõîäå: CF óñòàíîâëåí, åñëè èìåíà íå ñîâïàäàþò |
 öèêëå ïðîâåðÿåò ñîâïàäåíèå ïðèâåä¸ííûõ ê âåðõíåìó ðåãèñòðó î÷åðåäíûõ ñèìâîëîâ |
èì¸í ôàéëà è ýëåìåíòà. Óñëîâèÿ âûõîäà èç öèêëà: çàêîí÷èëîñü èìÿ ôàéëà |
â ds:si (òî åñòü, î÷åðåäíîé ñèìâîë - íóëåâîé ëèáî '/') - ñîâïàäåíèå |
âîçìîæíî òîëüêî â ñèòóàöèè òèïà èìåíè "filename.ext" è ýëåìåíòà |
"filename.ext;1" (â ISO9660 ";1" - âåðñèÿ ôàéëà, ýëåìåíòû ñ îäèíàêîâûìè |
èìåíàìè â ïàïêå îòñîðòèðîâàíû ïî óáûâàíèþ âåðñèé); |
íåñîâïàäåíèå ñèìâîëîâ - îçíà÷àåò, ÷òî èìåíà íå ñîâïàäàþò; |
çàêîí÷èëîñü èìÿ ýëåìåíòà - íóæíî ïðîâåðèòü, çàêîí÷èëîñü ëè ïðè ýòîì èìÿ |
ôàéëà, è â çàâèñèìîñòè îò ýòîãî ïðèíèìàòü ðåøåíèå î ñîâïàäåíèè. |
Ïðîöåäóðà ïðèâåäåíèÿ ñèìâîëà â âåðõíèé ðåãèñòð (toupper): |
íà âõîäå: ASCII-ñèìâîë |
íà âûõîäå: òîò æå ñèìâîë â âåðõíåì ðåãèñòðå (îí ñàì, åñëè ïîíÿòèå ðåãèñòðà ê |
íåìó íåïðèìåíèìî) |
Èç ñèìâîëîâ â äèàïàçîíå 'a' - 'z' âêëþ÷èòåëüíî âû÷èòàåò êîíñòàíòó 'a'-'A', |
îñòàëüíûå ñèìâîëû íå òðîãàåò. |
Ïðîöåäóðà ïîèñêà ôàéëà â äàííûõ ïàïêè (scan_for_filename_in_sector): |
íà âõîäå: |
ds:si = óêàçàòåëü íà èìÿ ôàéëà |
es:bx = óêàçàòåëü íà íà÷àëî äàííûõ ïàïêè |
es:dx = óêàçàòåëü íà êîíåö äàííûõ ïàïêè |
íà âûõîäå: |
CF ñáðîøåí, åñëè íàéäåí ôèíàëüíûé ôðàãìåíò ôàéëà |
(è äàëüøå ñêàíèðîâàòü ïàïêó íå íóæíî) |
â îáëàñòü äëÿ èíôîðìàöèè î ôðàãìåíòàõ ôàéëà çàïèñûâàåòñÿ íàéäåííîå |
 öèêëå ïðîñìàòðèâàåò âñå âõîäû ïàïêè, ïðîïóñêàÿ òå, ó êîòîðûõ óñòàíîâëåí |
áèò Associated (ýòî ñïåöèàëüíûå âõîäû, äîïîëíÿþùèå îñíîâíûå). Åñëè |
èìÿ î÷åðåäíîãî âõîäà ñîâïàäàåò ñ èìåíåì ôàéëà, òî çàïîìèíàåò íîâûé |
ôðàãìåíò. Åñëè ôðàãìåíò ôèíàëüíûé (íå óñòàíîâëåí áèò Multi-Extent), |
òî êîä âûõîäèò ñ CF=0. Åñëè äîñòèãíóò êîíåö äàííûõ, òî êîä âûõîäèò |
ñ CF=1. Åñëè î÷åðåäíîé âõîä íóëåâîé (ïåðâûé áàéò íàñòîÿùåãî âõîäà |
ñîäåðæèò äëèíó è íå ìîæåò áûòü íóë¸ì), òî ïðîöåäóðà ïåðåõîäèò ê |
ðàññìîòðåíèþ ñëåäóþùåãî ëîãè÷åñêîãî áëîêà. Ïðè ýòîì ïîòåíöèàëüíî |
âîçìîæíî ïåðåïîëíåíèå ïðè äîáàâëåíèè ðàçìåðà áëîêà; ïîñêîëüêó òàêîé |
ñöåíàðèé îçíà÷àåò, ÷òî ïðîöåäóðà âûçâàíà äëÿ êýøèðîâàííîé ïàïêè |
ñ ðàçìåðîì ïî÷òè 64K è íà÷àëîì äàííûõ bx=0 (ýòî ñâîéñòâî âûçûâàþùåãî |
êîäà), à ðàçìåð áëîêà - ñòåïåíü äâîéêè, òî ïîñëå ïåðåïîëíåíèÿ âñåãäà |
bx=0, òàê ÷òî ýòî ìîæíî îáíàðóæèòü ïî âçâåä¸ííîìó ZF ïîñëå ñëîæåíèÿ; |
â ýòîì ñëó÷àå òàêæå ïðîèñõîäèò âûõîä (à ïîñëå ïåðåïîëíåíèÿ CF=1). |
Ïðîöåäóðà ïåðåâîäà ëîãè÷åñêîãî áëîêà â íîìåð ñåêòîðà: |
íà âõîäå: eax = ëîãè÷åñêèé áëîê |
íà âûõîäå: eax = ôèçè÷åñêèé ñåêòîð, dx = íîìåð ëîãè÷åñêîãî áëîêà â ñåêòîðå |
Îñóùåñòâëÿåò îáû÷íîå äåëåíèå 32-áèòíîãî ÷èñëà íà 32-áèòíîå (÷èñëî ëîãè÷åñêèõ |
áëîêîâ â ñåêòîðå, õðàíÿùååñÿ âî âíóòðåííåé ïåðåìåííîé). |
Ïðîöåäóðà çàãðóçêè ôèçè÷åñêîãî ñåêòîðà, ñîäåðæàùåãî óêàçàííûé ëîãè÷åñêèé áëîê |
(load_phys_sector_for_lb_force): |
íà âõîäå: eax = ëîãè÷åñêèé áëîê; |
si - èíäèêàòîð, çàäàþùèé, ñëåäóåò ëè ÷èòàòü äàííûå â ñëó÷àå, |
åñëè ëîãè÷åñêèé áëîê íà÷èíàåòñÿ ñ íà÷àëà ôèçè÷åñêîãî: |
si = 0 - íå íóæíî, si íåíóëåâîé - íóæíî |
íà âûõîäå: |
ôèçè÷åñêèé ñåêòîð çàãðóæåí ïî àäðåñó 0000:1000 |
si óêàçûâàåò íà äàííûå ëîãè÷åñêîãî áëîêà |
CF óñòàíîâëåí ïðè îøèáêå ÷òåíèÿ |
Ïðåîáðàçóåò ïðåäûäóùåé ïðîöåäóðîé íîìåð ëîãè÷åñêîãî áëîêà â íîìåð ôèçè÷åñêîãî |
ñåêòîðà è íîìåð ëîãè÷åñêîãî áëîêà âíóòðè ñåêòîðà; åñëè ïîñëåäíÿÿ |
âåëè÷èíà íóëåâàÿ è íèêàêèõ äåéñòâèé â ýòîì ñëó÷àå íå çàïðîøåíî (si=0), |
òî íè÷åãî è íå äåëàåò; èíà÷å óñòàíàâëèâàåò si â ñîîòâåòñòâèè ñ íåé |
è ÷èòàåò ñåêòîð. |
Ïðîöåäóðû ÷òåíèÿ íóæíîãî ÷èñëà áàéò èç íåïðåðûâíîé öåïî÷êè ëîãè÷åñêèõ áëîêîâ |
(read_many_bytes è read_many_bytes.with_first): |
íà âõîäå: |
eax = ëîãè÷åñêèé áëîê |
esi = ÷èñëî áàéò äëÿ ÷òåíèÿ |
es:bx = óêàçàòåëü íà íà÷àëî áóôåðà, êóäà áóäóò ïðî÷èòàíû äàííûå |
cur_limit = ðàçìåð áóôåðà (íå ìåíüøå esi) |
íà âûõîäå: |
es:bx óêàçûâàåò íà êîíåö áóôåðà, â êîòîðûé áûëè ïðî÷èòàíû äàííûå |
åñëè ïðîèçîøëà îøèáêà ÷òåíèÿ, ôëàã CF óñòàíîâëåí |
cur_limit ñîîòâåòñòâóþùèì îáðàçîì óìåíüøåí |
Îòëè÷èå äâóõ ïðîöåäóð: âòîðàÿ äîïîëíèòåëüíî ïðèíèìàåò âî âíèìàíèå ïåðåìåííóþ |
[first_byte], íà÷èíàÿ ÷òåíèå ïåðâîãî áëîêà ñî ñìåùåíèÿ [first_byte]; |
ñîîòâåòñòâåííî, ïåðâàÿ ÷èòàåò áëîê ñ íà÷àëà, îáíóëÿÿ [first_byte] |
ïðè âõîäå. |
1. Îòäåëüíî ñ÷èòûâàåò ïåðâûé ôèçè÷åñêèé ñåêòîð âî âðåìåííóþ îáëàñòü 0000:1000, |
åñëè ïåðâûé ëîãè÷åñêèé áëîê íà÷èíàåòñÿ íå ñ íà÷àëà ñåêòîðà. Ïðè |
îøèáêå ÷òåíèÿ âûõîäèò èç ïðîöåäóðû. |
2. Ïåðåñûëàåò íóæíóþ ÷àñòü äàííûõ (âîçìîæíî, 0 áàéò), ïðî÷èòàííûõ â ï.1, |
â áóôåð. Íîðìàëèçóåò óêàçàòåëü íà áóôåð. |
3. Åñëè âñå íåîáõîäèìûå äàííûå óæå ïðî÷èòàíû, âûõîäèò èç ïðîöåäóðû. |
4. Äàëüíåéøèå äàííûå íàõîäÿòñÿ â íåñêîëüêèõ ôèçè÷åñêèõ ñåêòîðàõ, ïðè ýòîì, |
âîçìîæíî, ïîñëåäíèé ñåêòîð ñ÷èòûâàòü íóæíî íå öåëèêîì. |
5. Åñëè â áóôåðå åñòü ìåñòî äëÿ ñ÷èòûâàíèÿ âñåõ ñåêòîðîâ, òî ñðàçó ÷èòàþòñÿ |
âñå ñåêòîðà, ïîñëå ÷åãî óêàçàòåëü íà áóôåð íóæíûì îáðàçîì óìåíüøàåòñÿ. |
6. Åñëè æå íåò, òî ñ÷èòûâàþòñÿ âñå ñåêòîðà, êðîìå ïîñëåäíåãî, ïîñëå ÷åãî |
ïîñëåäíèé ñåêòîð ñ÷èòûâàåòñÿ îòäåëüíî âî âðåìåííóþ îáëàñòü, è óæå |
îòòóäà íóæíàÿ ÷àñòü äàííûõ êîïèðóåòñÿ â áóôåð. |
/kernel/trunk/bootloader/extended_primary_loader/cdfs |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/kernel/trunk/bootloader/extended_primary_loader/fat1x/kordldr.f1x.asm |
---|
0,0 → 1,688 |
; 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 |
readloop: |
push ax |
; buffer should not cross a 64K boundary |
push bx |
shr bx, 4 |
mov cx, es |
add bx, cx |
neg bx |
and bh, 0xF |
shr bx, 5 |
jnz @f |
mov bl, 0x80 |
@@: |
cmp ax, bx |
jbe @f |
xchg ax, bx |
@@: |
pop bx |
xchg ax, cx |
; calculate starting sector |
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 ax |
sub ax, cx |
jnz readloop |
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 'kernel.mnt',0 |
aKernelNotFound db 'Fatal error: cannot load the kernel',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/bootloader/extended_primary_loader/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/bootloader/extended_primary_loader/fat1x/build.bat |
---|
0,0 → 1,3 |
@fasm -m 65535 bootsect.asm bootsect.bin |
@fasm -m 65535 kordldr.f1x.asm kordldr.f1x |
@pause |
/kernel/trunk/bootloader/extended_primary_loader/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/bootloader/extended_primary_loader/fat1x |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |