Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 1064 → Rev 1065

/kernel/trunk/sec_loader/trunk/boot/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 'kord/loader',0
aKernelNotFound db 'Fatal error: cannot load the secondary loader',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 83FEh-$ 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/sec_loader/trunk/boot/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/sec_loader/trunk/boot/cdfs/.
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property