Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 5452 → Rev 9019

/kernel/branches/kolibri-ahci/sec_loader/trunk/startos.ini
0,0 → 1,98
; Copyright (c) 2009, <Lrz>
; 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.
;*****************************************************************************
 
; это комментарий
[loader]
; секция [loader] содержит параметры загрузчика
; в течение timeout секунд загрузчик будет ждать реакции пользователя,
; если её не последует, будет загружена конфигурация, указанная в default
timeout=5
default=kolibri_EE
; прочие секции - по одной на каждую конфигурацию
; и по одной на каждый вторичный модуль
[main]
name="Kord OS v 0.00001"
descript="This is x64 OS microkernel"
kernel=kord/kord001.ker
module=kord/fat.mod
module=kord/ntfs.mod
RamdiskFS=fat
RamdiskSector=512
RamdiskCluster=1
RamdiskSize=1440K
RamdiskFile=kord/launcher,launcher
RamdiskFile=kord/filema~1/kfar,"File Managers/kfar"
[beta]
name="Kord OS v 0.00002 beta"
descript="This is x64 OS microkernel version 2"
kernel=kord/kord002.ker
module=kord/fat.mod
module=kord/ntfs.mod
RamdiskFS=fat
RamdiskSector=512
RamdiskCluster=1
RamdiskSize=1440K
RamdiskFile=kord/launcher,launcher
RamdiskFile=kord/filema~1/kfar,"File Managers/kfar"
[kolibri_EE]
name="KOLIBRY EXCLUSIVE EDITION"
descript="KOLIBRY EXCLUSIVE EDITION BEST OF THE BEST opetation system"
LoaderModule=kolibri/kolibri.ldm
RamdiskFS=FAT
RamdiskSector=512
RamdiskCluster=1
RamdiskSize=1440K
LoaderRamImage=kolibri.img
RamdiskPATH=/kolibri/
RamdiskFile=@menu,@menu
RamdiskFile=@TASKBAR,@TASKBAR
RamdiskFile=@RB,@TASKBAR
 
[legacy_kolibri]
name="KolibriOS"
descript="Standart KolibriOS"
LoaderModule=kord/kolibri.ldm
RamdiskFS=fat
RamdiskSector=512
RamdiskCluster=1
RamdiskSize=1440K
RamdiskPATH=/kolibri/
RamdiskFile=@menu,@menu
RamdiskFile=@TASKBAR,@TASKBAR
RamdiskFile=@RB,@RB
RamdiskFile=@rcher,@rcher
RamdiskFile=@ss,@ss
RamdiskFile=ac97snd,ac97snd
RamdiskFile=animage,animage
RamdiskFile=AUTOEXEC.CMD,AUTOEXEC.CMD
RamdiskFile=AUTORUN.DAT,AUTORUN.DAT
RamdiskFile=calc,calc
RamdiskFile=calendar,calendar
RamdiskFile=progs/cdp,cdp
RamdiskFile=cmd,cmd
RamdiskFile=config.inc,config.inc
RamdiskFile=copy2,copy2
 
/kernel/branches/kolibri-ahci/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...
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/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/branches/kolibri-ahci/sec_loader/trunk/boot/cdfs/build.bat
0,0 → 1,2
@fasm -m 65535 bootsect.asm bootsect.bin
@pause
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/cdfs
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/PrimaryLoader.txt
0,0 → 1,91
; 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.
Загрузчик должен предоставлять следующие сервисы:
1. При загрузке компьютера, получив управление от BIOS'а, загружать
файл loader из папки kord по адресу 1000:0000.
Размер файла loader не превосходит 30000h = 192 Kb.
2. При этом устанавливать следующие регистры:
ax идентифицирует устройство:
al = тип:
'f' - флопик
'h' - HDD
'c' - CD/DVD
'u' - USB флешка
'?' - неизвестное устройство
ah = номер устройства (среди всех устройств фиксированного типа)
bx = тип файловой системы:
'12' = FAT12
'16' = FAT16
'32' = FAT32
'nt' = NTFS
'is' = ISO-9660
ds:si = far-указатель на callback-сервис
3. Предоставлять callback-сервис для вторичного загрузчика - far-процедуру:
на входе: ax = запрашиваемая функция
на выходе: CF=1, если функция не поддерживается; CF=0 иначе
Загрузчик может разрушать все регистры, включая сегментные,
за исключением ss и sp.
4. Всегда должна поддерживаться callback-функция 1:
назначение: прочитать файл, расположенный на загрузочном устройстве
на входе: ax = 1, ds:di = указатель на информационную структуру:
dw:dw far-указатель на буфер,
первое слово - смещение, второе - сегмент
dw максимальное число 4Kb-блоков для чтения (0x1000 байт)
должно быть ненулевым и строго меньше 0x100
ASCIIZ имя файла в формате "<папка1>/<папка2>/<файл>"
Если имя файла содержит символы из старшей половины
ASCIIZ-таблицы или не является 8.3-именем (в смысле, одна из компонент
имени файла имеет имя длиннее 8 символов или расширение длиннее 3),
загрузчик может не найти такой файл, даже если он есть
(а может и найти).
на выходе: bx = статус:
0 = успешно
1 = файл оказался слишком большим, буфер заполнен целиком
и есть ещё данные файла
2 = файл не найден
3 = произошла ошибка чтения
dx:ax = размер файла или FFFF:FFFF, если файл не найден
5. Всегда должна поддерживаться callback-функция 2:
назначение: продолжить чтение файла, частично загруженного функцией 1
на входе: ax = 2, ds:di = указатель на информационную структуру:
dw:dw far-указатель на буфер,
первое слово - смещение, второе - сегмент
dw максимальное число 4Kb-блоков для чтения (0x1000 байт)
должно быть ненулевым и строго меньше 0x100
на выходе: bx = статус:
0 = успешно
1 = файл оказался слишком большим, буфер заполнен целиком
и есть ещё данные файла
3 = произошла ошибка чтения
dx:ax = размер файла
Функцию можно вызывать только в случае, когда последний вызов функции
1 и все последующие вызовы функции 2 вернули bx=1 (иными словами,
только для продолжения загрузки файла, который уже был частично
загружен, но ещё не загружен полностью).
Загрузчик может быть уверен, что данные в областях памяти 0-9000 и
60000-A0000 не будут модифицированы ядром.
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/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/branches/kolibri-ahci/sec_loader/trunk/boot/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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/after_win/kordldr.win.asm
0,0 → 1,924
; 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 'kord/loader',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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/after_win/build.bat
0,0 → 1,2
@fasm -m 65535 kordldr.win.asm kordldr.win
@pause
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/after_win
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/fat1x/bootsect.txt
0,0 → 1,360
; Copyright (c) 2008-2009, diamond
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the <organization> nor the
; names of its contributors may be used to endorse or promote products
; derived from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;*****************************************************************************
 
Встречаются вирус и FAT.
- Привет, ты кто?
- Я? Вирус.
- A я AFT, то есть TAF, то есть FTA, черт, совсем запутался...
 
Бутсектор для FAT12/FAT16-тома на носителе с размером сектора 0x200 = 512 байт.
 
=====================================================================
 
Есть две версии в зависимости от того, поддерживает ли носитель LBA,
выбор осуществляется установкой константы use_lba в первой строке исходника.
Требования для работы:
1) Сам бутсектор, первая копия FAT и все используемые файлы
должны быть читабельны.
2) Минимальный процессор - 80186.
3) В системе должно быть как минимум 592K свободной базовой памяти.
 
=====================================================================
 
Документация в тему (ссылки валидны на момент написания этого файла, 15.05.2008):
официальная спецификация FAT: http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
в формате PDF: http://staff.washington.edu/dittrich/misc/fatgen103.pdf
русский перевод: http://wasm.ru/docs/11/fatgen103-rus.zip
официальная спецификация расширения EDD BIOS 3.0: http://www.phoenix.com/NR/rdonlyres/19FEBD17-DB40-413C-A0B1-1F3F560E222F/0/specsedd30.pdf
то же, версия 1.1: http://www.phoenix.com/NR/rdonlyres/9BEDED98-6B3F-4DAC-BBB7-FA89FA5C30F0/0/specsedd11.pdf
описание функций BIOS: Interrupt List by Ralf Brown: http://www.cs.cmu.edu/~ralf/files.html
официальная спецификация Boot BIOS: http://www.phoenix.com/NR/rdonlyres/56E38DE2-3E6F-4743-835F-B4A53726ABED/0/specsbbs101.pdf
 
=====================================================================
 
Максимальное количество кластеров на FAT12-томе - 0xFF4 = 4084; каждый кластер
занимает 12 бит в таблице FAT, так что общий размер не превосходит
0x17EE = 6126 байт. Вся таблица помещается в памяти.
Максимальное количество кластеров на FAT16-томе - 0xFFF4 = 65524; каждый
кластер занимает 16 бит в таблице FAT, так что общий размер не превосходит
0x1FFE8 = 131048 байт. Вся таблица также помещается в памяти, однако в
этом случае несколько нецелесообразно считывать всю таблицу, поскольку
на практике нужна только небольшая её часть. Поэтому место в памяти
резервируется, но данные считываются только в момент, когда к ним
действительно идёт обращение.
 
Схема используемой памяти:
...-7C00 стек
7C00-7E00 код бутсектора
7E00-8200 вспомогательный файл загрузчика (kordldr.f1x)
8200-8300 список загруженных секторов таблицы FAT16
(1 = соответствующий сектор загружен)
60000-80000 загруженная таблица FAT12 / место для таблицы FAT16
80000-90000 текущий кластер текущей рассматриваемой папки
90000-92000 кэш для корневой папки
92000-... кэш для некорневых папок (каждой папке отводится
2000h байт = 100h входов, одновременно в кэше
может находиться не более 7 папок;
точный размер определяется размером доступной
физической памяти - как правило, непосредственно
перед A0000 размещается EBDA, Extended BIOS Data Area)
 
=====================================================================
 
Основной процесс загрузки.
Точка входа (start): получает управление от BIOS при загрузке, при этом
dl содержит идентификатор диска, с которого идёт загрузка
1. Настраивает стек ss:sp = 0:7C00 (стек располагается непосредственно перед
кодом), сегмент данных ds = 0, и устанавливает ss:bp на начало
бутсектора (в дальнейшем данные будут адресоваться через [bp+N] -
это освобождает ds и экономит на размере кода).
2. LBA-версия: проверяет, поддерживает ли носитель LBA, вызовом функции 41h
прерывания 13h. Если нет, переходит на код обработки ошибок с
сообщением об отсутствии LBA.
CHS-версия: определяет геометрию носителя вызовом функции 8 прерывания 13h и
записывает полученные данные поверх BPB. Если вызов завершился ошибкой,
предполагает уже существующие данные корректными.
3. Вычисляет некоторые параметры FAT-тома: начальный сектор корневой папки
и начальный сектор данных. Кладёт их в стек; впоследствии они
всегда будут лежать в стеке и адресоваться через bp.
4. Считывает начало корневой папки по адресу 9000:0000. Число считываемых
секторов - минимум из размера корневой папки, указанного в BPB, и 16
(размер кэша для корневой папки - 2000h байт = 16 секторов).
5. Ищет в корневой папке элемент kordldr.f1x. Если не находит, или если
он оказывается папкой, или если файл имеет нулевую длину -
переходит на код обработки ошибок с сообщением о
ненайденном загрузчике.
Замечание: на этом этапе загрузки искать можно только в корневой
папке и только имена, заданные в формате файловой системе FAT
(8+3 - 8 байт на имя, 3 байта на расширение, все буквы должны
быть заглавными, при необходимости имя и расширение дополняются
пробелами, разделяющей точки нет, завершающего нуля нет).
6. Загружает первый кластер файла kordldr.f1x по адресу 0:7E00 и передаёт
ему управление. При этом в регистрах dx:ax оказывается абсолютный
номер первого сектора kordldr.f1x, а в cx - число считанных секторов
(равное размеру кластера).
 
Вспомогательные процедуры бутсектора.
Код обработки ошибок (err):
1. Выводит строку с сообщением об ошибке.
2. Выводит строку "Press any key...".
3. Ждёт нажатия any key.
4. Вызывает int 18h, давая шанс BIOSу попытаться загрузиться откуда-нибудь ещё.
5. Для подстраховки зацикливается.
 
Процедура чтения секторов (read_sectors и read_sectors2):
на входе должно быть установлено:
ss:bp = 0:7C00
es:bx = указатель на начало буфера, куда будут прочитаны данные
dx:ax = стартовый сектор (относительно начала логического диска
для read_sectors, относительно начала данных для read_sectors2)
cx = число секторов (должно быть больше нуля)
на выходе: es:bx указывает на конец буфера, в который были прочитаны данные
0. Если вызывается read_sectors2, она переводит указанный ей номер сектора
в номер относительно начала логического диска, прибавляя номер сектора
начала данных, хранящийся в стеке как [bp-8].
1. Переводит стартовый сектор (отсчитываемый от начала тома) в сектор на
устройстве, прибавляя значение соответствующего поля из BPB.
2. В цикле (шаги 3-6) читает секторы, следит за тем, чтобы на каждой итерации
CHS-версия: все читаемые секторы были на одной дорожке.
LBA-версия: число читаемых секторов не превосходило 7Fh (требование
спецификации EDD BIOS).
CHS-версия:
3. Переводит абсолютный номер сектора в CHS-систему: сектор рассчитывается как
единица плюс остаток от деления абсолютного номера на число секторов
на дорожке; дорожка рассчитывается как остаток от деления частного,
полученного на предыдущем шаге, на число дорожек, а цилиндр - как
частное от этого же деления. Если число секторов для чтения больше,
чем число секторов до конца дорожки, уменьшает число секторов для
чтения.
4. Формирует данные для вызова int 13h (ah=2 - чтение, al=число секторов,
dh=головка, (младшие 6 бит cl)=сектор,
(старшие 2 бита cl и весь ch)=дорожка, dl=диск, es:bx->буфер).
5. Вызывает BIOS. Если BIOS рапортует об ошибке, выполняет сброс диска
и повторяет попытку чтения, всего делается не более трёх попыток
(несколько попыток нужно в случае дискеты для гарантии того, что
мотор раскрутился). Если все три раза происходит ошибка чтения,
переходит на код обработки ошибок с сообщением "Read error".
6. В соответствии с числом прочитанных на текущей итерации секторов
корректирует текущий сектор, число оставшихся секторов и указатель на
буфер (в паре es:bx корректируется es). Если всё прочитано, заканчивает
работу, иначе возвращается на шаг 3.
LBA-версия:
3. Если число секторов для чтения больше 7Fh, уменьшает его (для текущей
итерации) до 7Fh.
4. Формирует в стеке пакет для int 13h (кладёт все нужные данные командами
push, причём в обратном порядке: стек - структура LIFO, и данные в
стеке хранятся в обратном порядке по отношению к тому, как их туда
клали).
5. Вызывает BIOS. Если BIOS рапортует об ошибке, переходит на код обработки
ошибок с сообщением "Read error". Очищает стек от пакета,
сформированного на предыдущем шаге.
6. В соответствии с числом прочитанных на текущей итерации секторов
корректирует текущий сектор, число оставшихся секторов и указатель на
буфер (в паре es:bx корректируется es). Если всё прочитано, заканчивает
работу, иначе возвращается на шаг 3.
 
Процедура поиска элемента по имени в уже прочитанных данных папки
(scan_for_filename):
на входе должно быть установлено:
ds:si = указатель на имя файла в формате FAT (11 байт, 8 на имя,
3 на расширение, все буквы заглавные, если имя/расширение
короче, оно дополняется до максимума пробелами)
es = сегмент данных папки
cx = число элементов в прочитанных данных
на выходе: ZF определяет, нужно ли продолжать разбор данных папки
(ZF=1, если либо найден запрошенный элемент, либо достигнут
конец папки); CF определяет, удалось ли найти элемент с искомым именем
(CF=1, если не удалось); если удалось, то es:di указывает на него.
scan_for_filename считает, что данные папки размещаются начиная с es:0.
Первой командой процедура обнуляет di. Затем просто в цикле по элементам папки
проверяет имена.
 
Процедура поиска элемента в корневой папке (lookup_in_root_dir):
на входе должно быть установлено:
ss:bp = 0:7C00
ds:si = указатель на имя файла в формате FAT (см. выше)
на выходе: флаг CF определяет, удалось ли найти файл; если удалось, то
CF сброшен и es:di указывает на элемент папки
Начинает с просмотра кэшированной (начальной) части корневой папки. В цикле
сканирует элементы; если по результатам сканирования обнаруживает,
что нужно читать папку дальше, то считывает не более 0x10000 = 64K
байт (ограничение введено по двум причинам: во-первых, чтобы заведомо
не вылезти за пределы используемой памяти, во-вторых, сканирование
предполагает, что все обрабатываемые элементы располагаются в одном
сегменте) и продолжает цикл.
Сканирование прекращается в трёх случаях: обнаружен искомый элемент;
кончились элементы в папке (судя по числу элементов, указанному в BPB);
очередной элемент папки сигнализирует о конце (первый байт нулевой).
 
Процедура вывода на экран ASCIIZ-строки (out_string):
на входе: ds:si -> строка
В цикле, пока не достигнут завершающий ноль, вызывает функцию int 10h/ah=0Eh.
 
=====================================================================
 
Работа вспомогательного загрузчика kordldr.f1x:
1. Определяет, был ли он загружен CHS- или LBA-версией бутсектора.
В зависимости от этого устанавливает смещения используемых процедур
бутсектора. Критерий проверки: scan_for_filename должна начинаться
с инструкции 'xor di,di' с кодом 31 FF (вообще-то эта инструкция может
с равным успехом ассемблироваться и как 33 FF, но fasm генерирует
именно такую форму).
2. Узнаёт размер свободной базовой памяти (т.е. свободного непрерывного куска
адресов памяти, начинающегося с 0) вызовом int 12h. В соответствии с
ним вычисляет число элементов в кэше папок. Хотя бы для одного элемента
место должно быть, отсюда ограничение в 592 Kb (94000h байт).
Замечание: этот размер не может превосходить 0A0000h байт и
на практике оказывается немного (на 1-2 килобайта) меньшим из-за
наличия дополнительной области данных BIOS "вверху" базовой памяти.
3. Определяет тип файловой системы: FAT12 или FAT16. Согласно официальной
спецификации от Microsoft (версия 1.03 спецификации датирована,
к слову, 06 декабря 2000 года), разрядность FAT определяется
исключительно числом кластеров: максимальное число кластеров на
FAT12-томе равно 4094 = 0xFF4. Согласно здравому смыслу, на FAT12
может быть 0xFF5 кластеров, но не больше: кластеры нумеруются с 2,
а число 0xFF7 не может быть корректным номером кластера.
Win95/98/Me следует здравому смыслу: разграничение FAT12/16 делается
по максимуму 0xFF5. Драйвер FAT в WinNT/2k/XP/Vista вообще поступает
явно неверно, считая, что 0xFF6 (или меньше) кластеров означает
FAT12-том, в результате получается, что последний кластер
(в случае 0xFF6) неадресуем. Основной загрузчик osloader.exe
[встроен в ntldr] для NT/2k/XP делает так же. Первичный загрузчик
[бутсектор FAT12/16 загружает первый сектор ntldr, и разбор FAT-таблицы
лежит на нём] в NT/2k подвержен той же ошибке. В XP её таки исправили
в соответствии со спецификацией. Linux при определении FAT12/FAT16
честно следует спецификации.
Здесь код основан всё же на спецификации. 9x мертва, а в линейке NT
Microsoft если и будет исправлять ошибки, то согласно собственному
описанию.
4. Для FAT12: загружает в память первую копию таблицы FAT по адресу 6000:0000.
Если размер, указанный в BPB, превосходит 12 секторов,
это означает, что заявленный размер слишком большой (это не считается
ошибкой файловой системы), и читаются только 12 секторов (таблица FAT12
заведомо влезает в такой объём данных).
Для FAT16: инициализирует внутренние данные, указывая, что никакой сектор
FAT не загружен (они будут подгружаться позднее, когда понадобятся
и только те, которые понадобятся).
5. Если кластер равен сектору, то бутсектор загрузил только часть файла
kordldr.f1x, и загрузчик подгружает вторую свою часть, используя
значения регистров на входе в kordldr.f1x.
6. Загружает вторичный загрузчик kord/loader по адресу 1000:0000. Если файл не
найден, или оказался папкой, или оказался слишком большим, то переходит
на код обработки ошибок из бутсектора с сообщением
"Fatal error: cannot load the secondary loader".
Замечание: на этом этапе имя файла уже можно указывать вместе с путём
и в формате ASCIIZ, хотя поддержки длинных имён и неанглийских символов
по-прежнему нет.
7. Изменяет код обработки ошибок бутсектора на переход на метку hooked_err.
Это нужно, чтобы последующие обращения к коду бутсектора в случае
ошибок чтения не выводил соответствующее сообщение с последующей
перезагрузкой, а рапортовал об ошибке чтения, которую мог бы
как-нибудь обработать вторичный загрузчик.
8. Если загрузочный диск имеет идентификатор меньше 0x80,
то устанавливает al='f' ("floppy"), ah=идентификатор диска,
иначе al='h' ("hard"), ah=идентификатор диска-0x80 (номер диска).
Устанавливает bx='12', если тип файловой системы - FAT12, и
bx='16' в случае FAT16. Устанавливает si=смещение функции обратного
вызова. Поскольку в этот момент ds=0, то ds:si образуют полный адрес.
9. Передаёт управление по адресу 1000:0000.
 
Функция обратного вызова для вторичного загрузчика:
предоставляет возможность чтения файла.
Вход и выход описаны в спецификации на загрузчик.
1. Сохраняет стек вызывающего кода и устанавливает свой стек:
ss:sp = 0:(7C00-8), bp=7C00: пара ss:bp при работе с остальным
кодом должна указывать на 0:7C00, а -8 берётся от того, что
инициализирующий код бутсектора уже поместил в стек 2 двойных слова,
и они должны сохраняться в неизменности.
2. Разбирает переданные параметры, выясняет, какое действие запрошено,
и вызывает нужную вспомогательную процедуру.
3. Восстанавливает стек вызывающего кода и возвращает управление.
 
Вспомогательные процедуры kordldr.f1x.
Процедура получения следующего кластера в FAT (get_next_cluster):
1. Вспоминает разрядность FAT, вычисленную ранее.
Для FAT12:
2. Устанавливает ds = 0x6000 - сегмент, куда ранее была считана
вся таблица FAT.
3. Подсчитывает si = (кластер) + (кластер)/2 - смещение в этом сегменте
слова, задающего следующий кластер. Загружает слово по этому адресу.
4. Если кластер имеет нечётный номер, то соответствующий ему элемент
располагается в старших 12 битах слова, и слово нужно сдвинуть вправо
на 4 бита; в противном случае - в младших 12 битах, и делать ничего не
надо.
5. Выделяет из получившегося слова 12 бит. Сравнивает их с пределом 0xFF7:
номера нормальных кластеров меньше, и флаг CF устанавливается;
специальные значения EOF и BadClus сбрасывают флаг CF.
Для FAT16:
2. Вычисляет адрес памяти, предназначенной для соответствующего сектора данных
в таблице FAT.
3. Если сектор ещё не загружен, то загружает его.
4. Вычисляет смещение данных для конкретного кластера относительно начала
сектора.
5. Загружает слово в ax из адреса, вычисленному на шагах 1 и 3.
6. Сравнивает его с пределом 0xFFF7: номера нормальных кластеров меньше, и флаг
CF устанавливается; специальные значения EOF и BadClus сбрасывают CF.
 
Процедура загрузки файла (load_file):
1. Текущая рассматриваемая папка - корневая. В цикле выполняет шаги 2-4.
2. Конвертирует имя текущего рассматриваемого компонента имени (компоненты
разделяются символом '/') в FAT-формат 8+3. Если это невозможно
(больше 8 символов в имени, больше 3 символов в расширении или
больше одной точки), возвращается с ошибкой.
3. Ищет элемент с таким именем в текущей рассматриваемой папке. Для корневой
папки используется процедура из бутсектора. Для остальных папок:
a) Проверяет, есть ли такая папка в кэше некорневых папок.
(Идентификация папок осуществляется по номеру начального кластера.)
Если такой папки ещё нет, добавляет её в кэш; если тот переполняется,
выкидывает папку, к которой дольше всего не было обращений. (Для
каждого элемента кэша хранится метка от 0 до (размер кэша)-1,
определяющая его номер при сортировке по давности последнего обращения.
При обращении к какому-то элементу его метка становится нулевой,
а те метки, которые меньше старого значения, увеличиваются на единицу.)
б) Просматривает в поисках запрошенного имени все элементы из кэша,
используя процедуру из бутсектора. Если обнаруживает искомый элемент,
переходит к шагу 4. Если обнаруживает конец папки, возвращается из
процедуры с ошибкой.
в) В цикле считывает папку посекторно. При этом пропускает начальные
секторы, которые уже находятся в кэше и уже были просмотрены. Каждый
прочитанный сектор копирует в кэш, если там ещё остаётся место,
и просматривает в нём все элементы. Работает, пока не случится одно из
трёх событий: найден искомый элемент; кончились кластеры (судя по
цепочке кластеров в FAT); очередной элемент папки сигнализирует о конце
(первый байт нулевой). В двух последних случаях возвращается с ошибкой.
4. Проверяет тип найденного элемента (файл/папка): последний элемент в
запрошенном имени должен быть файлом, все промежуточные - папками.
Если текущий компонент имени - промежуточный, продвигает текущую
рассматриваемую папку и возвращается к пункту 2.
5. Проходит по цепочке кластеров в FAT и считывает все кластеры в указанный
при вызове буфер последовательными вызовами функции бутсектора;
при этом если несколько кластеров файла расположены на диске
последовательно, то их чтение объединяется в одну операцию.
Следит за тем, чтобы не превысить указанный при вызове процедуры
лимит числа секторов для чтения.
 
Процедура продолжения загрузки файла (continue_load_file): встроена
внутрь шага 5 load_file; загружает в регистры нужные значения (ранее
сохранённые из load_file) и продолжает шаг 5.
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/fat1x/bootsect.asm
0,0 → 1,392
; Copyright (c) 2008-2009, diamond
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the <organization> nor the
; names of its contributors may be used to endorse or promote products
; derived from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;*****************************************************************************
 
use_lba = 0
org 0x7C00
jmp start
nop
; FAT parameters, BPB
; note: they can be changed at install, replaced with real values
; these settings are for most typical 1.44M floppies
db 'KOLIBRI ' ; BS_OEMName, ignored
dw 200h ; BPB_BytsPerSec
BPB_SecsPerClus db 1
BPB_RsvdSecCnt dw 1
BPB_NumFATs db 2
BPB_RootEntCnt dw 0xE0
dw 2880 ; BPB_TotSec16
db 0xF0 ; BPB_Media
BPB_FATSz16 dw 9
BPB_SecPerTrk dw 18
BPB_NumHeads dw 2
BPB_HiddSec dd 0
dd 0 ; BPB_TotSec32
BS_DrvNum db 0
db 0 ; BS_Reserved1
db ')' ; BS_BootSig
dd 12344321h ; BS_VolID
filename:
db 'KORD.OS ' ; BS_VolLab
db 'FAT12 ' ; BS_FilSysType
; Used memory map:
; 8000:0000 - current directory
; 9000:0000 - root directory data [cached]
start:
xor ax, ax
mov ss, ax
mov sp, 0x7C00
mov ds, ax
mov bp, sp
cld
sti
mov [bp+BS_DrvNum-0x7C00], dl
if use_lba
mov ah, 41h
mov bx, 55AAh
int 13h
mov si, aNoLBA
jc err_
cmp bx, 0AA55h
jnz err_
test cx, 1
jz err_
else
mov ah, 8
int 13h
jc @f ; on error, assume that BPB geometry is valid
mov al, dh
mov ah, 0
inc ax
mov [bp+BPB_NumHeads-0x7C00], ax
and cx, 3Fh
mov [bp+BPB_SecPerTrk-0x7C00], cx
@@:
end if
; get FAT parameters
xor bx, bx
mov al, [bp+BPB_NumFATs-0x7C00]
mov ah, 0
mul [bp+BPB_FATSz16-0x7C00]
add ax, [bp+BPB_RsvdSecCnt-0x7C00]
adc dx, bx
push dx
push ax ; root directory start = dword [bp-4]
mov cx, [bp+BPB_RootEntCnt-0x7C00]
add cx, 0xF
rcr cx, 1
shr cx, 3 ; cx = size of root directory in sectors
add ax, cx
adc dx, bx
push dx
push ax ; data start = dword [bp-8]
; load start of root directory (no more than 0x2000 bytes = 0x10 sectors)
cmp cx, 0x10
jb @f
mov cx, 0x10
@@:
mov ax, [bp-4]
mov dx, [bp-2]
push 0x9000
pop es
call read_sectors
add word [bp-4], cx ; dword [bp-4] = start of non-cached root data
adc word [bp-2], bx
; load kordldr.f12
mov si, main_loader
call lookup_in_root_dir
jc noloader
test byte [es:di+11], 10h ; directory?
jz kordldr_ok
noloader:
mov si, aLoaderNotFound
err_:
call out_string
mov si, aPressAnyKey
call out_string
xor ax, ax
int 16h
int 18h
jmp $
kordldr_ok:
mov ax, [es:di+26] ; get file cluster
mov bx, 0x7E00
xor cx, cx
mov es, cx
sub ax, 2
jc noloader
push bx ; save return address: bx = 7E00
mov cl, [bp+BPB_SecsPerClus-0x7C00]
mul cx
; fall through - 'ret' in read_sectors will return to 7E00
 
read_sectors2:
; same as read_sectors, but dx:ax is relative to start of data
add ax, [bp-8]
adc dx, [bp-6]
read_sectors:
; ss:bp = 0:7C00
; es:bx = pointer to data
; dx:ax = first sector
; cx = number of sectors
pusha
add ax, word [bp+BPB_HiddSec-0x7C00]
adc dx, word [bp+BPB_HiddSec+2-0x7C00]
if use_lba
push ds
do_read_sectors:
push ax
push cx
push dx
cmp cx, 0x7F
jbe @f
mov cx, 0x7F
@@:
; create disk address packet on the stack
; dq starting LBA
push 0
push 0
push dx
push ax
; dd buffer
push es
push bx
; dw number of blocks to transfer (no more than 0x7F)
push cx
; dw packet size in bytes
push 10h
; issue BIOS call
push ss
pop ds
mov si, sp
mov dl, [bp+BS_DrvNum-0x7C00]
mov ah, 42h
int 13h
mov si, aReadError
jc err_
; restore stack
add sp, 10h
; increase current sector & buffer; decrease number of sectors
mov si, cx
mov ax, es
shl cx, 5
add ax, cx
mov es, ax
pop dx
pop cx
pop ax
add ax, si
adc dx, 0
sub cx, si
jnz do_read_sectors
pop ds
popa
ret
else
do_read_sectors:
pusha
pop di
push bx
 
; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx
mov si, ax
xchg ax, dx
xor dx, dx
div [bp+BPB_SecPerTrk-0x7C00]
push ax
mov ax, si
div [bp+BPB_SecPerTrk-0x7C00]
mov bx, dx ; bx=sector-1
pop dx
 
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx
div [bp+BPB_NumHeads-0x7C00]
 
; number of sectors: read no more than to end of track
push bx
sub bx, [bp+BPB_SecPerTrk-0x7C00]
neg bx
cmp cx, bx
jbe @f
mov cx, bx
@@:
pop bx
 
inc bx
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format
mov di, cx
mov dh, dl
mov dl, [bp+BS_DrvNum-0x7C00]
shl ah, 6
mov ch, al
mov al, cl
mov cl, bl
or cl, ah
pop bx
mov si, 3
mov ah, 2
@@:
push ax
int 13h
jnc @f
xor ax, ax
int 13h ; reset drive
pop ax
dec si
jnz @b
mov si, aReadError
jmp err_
@@:
pop ax
mov ax, es
mov cx, di
shl cx, 5
add ax, cx
mov es, ax
push di
popa
add ax, di
adc dx, 0
sub cx, di
jnz do_read_sectors
popa
ret
end if
 
scan_for_filename:
; in: ds:si -> 11-bytes FAT name
; in: es:0 -> part of directory data
; in: cx = number of entries
; out: if found: CF=0, ZF=1, es:di -> directory entry
; out: if not found, but continue required: CF=1 and ZF=0
; out: if not found and zero item reached: CF=1 and ZF=1
xor di, di
push cx
sloop:
cmp byte [es:di], 0
jz snotfound
test byte [es:di+11], 8 ; volume label?
jnz scont ; ignore volume labels
pusha
mov cx, 11
repz cmpsb
popa
jz sdone
scont:
add di, 0x20
loop sloop
inc cx ; clear ZF flag
snotfound:
stc
sdone:
pop cx
lrdret:
ret
 
lookup_in_root_dir:
; ss:bp = 0:7C00
; in: ds:si -> 11-bytes FAT name
; out: if found: CF=0, es:di -> directory entry
; out: if not found: CF=1
mov cx, [bp+BPB_RootEntCnt-0x7C00]
push cx
; first, look in root directory cache
push 0x9000
pop es
test ch, ch
jz @f
mov cx, 0x100
@@:
mov ax, [bp-4]
mov dx, [bp-2] ; dx:ax = starting sector of not cached data of root directory
lrdloop:
call scan_for_filename
pop bx
jz lrdret
sub bx, cx
mov cx, bx
stc
jz lrdret
; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries
push cx
cmp ch, 0x8
jb @f
mov cx, 0x800
@@:
push 0x8000
pop es
push cx
push es
xor bx, bx
add cx, 0xF
shr cx, 4
call read_sectors
pop es
add ax, cx
adc dx, bx
pop cx
jmp lrdloop
 
out_string:
; in: ds:si -> ASCIIZ string
lodsb
test al, al
jz lrdret
mov ah, 0Eh
mov bx, 7
int 10h
jmp out_string
 
aReadError db 'Read error',0
if use_lba
aNoLBA db 'The drive does not support LBA!',0
end if
aLoaderNotFound db 'Loader not found',0
aPressAnyKey db 13,10,'Press any key...',13,10,0
main_loader db 'KORDLDR F1X'
 
if use_lba
db 0 ; make bootsector 512 bytes in length
end if
 
; bootsector signature
dw 0xAA55
 
; display offsets of all procedures used by kordldr.f12.asm
macro show [procedure]
{
bits = 16
display `procedure,' = '
repeat bits/4
d = '0' + procedure shr (bits - %*4) and 0Fh
if d > '9'
d = d + 'A'-'9'-1
end if
display d
end repeat
display 13,10
}
 
show read_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err_, noloader
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/fat1x/kordldr.f1x.asm
0,0 → 1,668
; Copyright (c) 2008-2009, diamond
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the <organization> nor the
; names of its contributors may be used to endorse or promote products
; derived from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;*****************************************************************************
 
org 0x7E00
; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here
; ss:bp = 0:7C00
virtual at bp
rb 3 ; BS_jmpBoot
rb 8 ; BS_OEMName, ignored
dw ? ; BPB_BytsPerSec
BPB_SecsPerClus db ?
BPB_RsvdSecCnt dw ?
BPB_NumFATs db ?
BPB_RootEntCnt dw ?
BPB_TotSec16 dw ?
db ? ; BPB_Media
BPB_FATSz16 dw ?
BPB_SecPerTrk dw ?
BPB_NumHeads dw ?
BPB_HiddSec dd ?
BPB_TotSec32 dd ?
BS_DrvNum db ?
fat_type db ? ; this is BS_Reserved1,
; we use it to save FS type: 0=FAT12, 1=FAT16
db ? ; BS_BootSig
num_sectors dd ? ; BS_VolID
; rb 11 ; BS_VolLab
; rb 3 ; BS_FilSysType, first 3 bytes
read_sectors dw ?
read_sectors2 dw ?
lookup_in_root_dir dw ?
scan_for_filename dw ?
err_ dw ?
noloader dw ?
cachelimit dw ?
filesize: ; will be used to save file size
rb 5 ; BS_FilSysType, last 5 bytes
; following variables are located in the place of starting code;
; starting code is no more used at this point
sect_per_clus dw ?
cur_cluster dw ?
next_cluster dw ?
flags dw ?
cur_delta dd ?
end virtual
 
; procedures from boot sector
; LBA version
lba_read_sectors = 7CE2h
lba_read_sectors2 = 7CDCh
lba_lookup_in_root_dir = 7D4Fh
lba_scan_for_filename = 7D2Dh
lba_err = 7CB5h
lba_noloader = 7CB2h
; CHS version
chs_read_sectors = 7CDEh
chs_read_sectors2 = 7CD8h
chs_lookup_in_root_dir = 7D70h
chs_scan_for_filename = 7D4Eh
chs_err = 7CB1h
chs_noloader = 7CAEh
 
push ax cx ; save our position on disk
push ss
pop es
; determine version of bootsector (LBA vs CHS)
; mov [read_sectors], chs_read_sectors
; mov [read_sectors2], chs_read_sectors2
; mov [lookup_in_root_dir], chs_lookup_in_root_dir
; mov [scan_for_filename], chs_scan_for_filename
; mov [err], chs_err
; mov [noloader], chs_noloader
lea di, [read_sectors]
mov si, chs_proc_addresses
mov cx, 6*2
cmp word [chs_scan_for_filename], 0xFF31 ; 'xor di,di'
jz @f
add si, cx
; mov [read_sectors], lba_read_sectors
; mov [read_sectors2], lba_read_sectors2
; mov [lookup_in_root_dir], lba_lookup_in_root_dir
; mov [scan_for_filename], lba_scan_for_filename
; mov [err], lba_err
; mov [noloader], lba_noloader
@@:
rep movsb
mov cl, [BPB_SecsPerClus]
mov [sect_per_clus], cx
xor bx, bx
; determine size of cache for folders
int 12h ; ax = size of available base memory in Kb
sub ax, 94000h / 1024
jae @f
nomem:
mov si, nomem_str
jmp [err_]
@@:
shr ax, 3
mov [cachelimit], ax ; size of cache - 1
; get type of file system - FAT12 or FAT16?
; calculate number of clusters
mov ax, [BPB_TotSec16]
xor dx, dx
test ax, ax
jnz @f
mov ax, word [BPB_TotSec32]
mov dx, word [BPB_TotSec32+2]
@@:
sub ax, [bp-8] ; dword [bp-8] = first data sector
sbb dx, [bp-6]
jb j_noloader
div [sect_per_clus]
; ax = number of clusters
; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes
mov [fat_type], ch
cmp ax, 0xFF5
jb init_fat12
inc [fat_type]
init_fat16:
; no sectors loaded
mov di, 0x8200
xor ax, ax
mov cx, 0x100/2
rep stosw
jmp init_fat_done
init_fat12:
; read FAT
push 0x6000
pop es
mov ax, [BPB_RsvdSecCnt]
mov cx, [BPB_FATSz16]
cmp cx, 12
jb @f
mov cx, 12
@@:
xor dx, dx
call [read_sectors]
init_fat_done:
; if cluster = sector, we need to read second part of our file
; (bootsector loads only first cluster of kordldr.f1x)
pop cx ax ; restore our position on disk
cmp cx, 1
ja kordldr_full
sub ax, [bp-8]
inc ax
inc ax ; ax = first cluster of kordldr.f12
call get_next_cluster
jc @f
j_noloader:
jmp [noloader]
@@:
dec ax
dec ax
push 0x800
pop es
call [read_sectors2]
kordldr_full:
; ...continue loading...
mov di, secondary_loader_info
call load_file
test bx, bx
mov bx, [err_]
jz @f
mov si, aKernelNotFound
jmp bx
@@:
; for subsequent calls to callback function, hook error handler
; mov byte [bx], 0xE9 ; 'jmp' opcode
; mov ax, hooked_err - 3
; sub ax, bx
; mov word [bx+1], ax
; push hooked_err / ret
mov word [bx], 0x68 + ((hooked_err and 0xFF) shl 8)
mov word [bx+2], (hooked_err shr 8) + (0xC3 shl 8)
; set registers for secondary loader
mov ah, [BS_DrvNum]
mov al, 'f'
test ah, ah
jns @f
sub ah, 80h
mov al, 'h'
@@:
mov bx, '12'
cmp [fat_type], 0
jz @f
mov bh, '6'
@@:
mov si, callback ; ds:si = far pointer to callback procedure
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000
 
nomem_str db 'No memory',0
 
chs_proc_addresses:
dw chs_read_sectors
dw chs_read_sectors2
dw chs_lookup_in_root_dir
dw chs_scan_for_filename
dw chs_err
dw chs_noloader
lba_proc_addresses:
dw lba_read_sectors
dw lba_read_sectors2
dw lba_lookup_in_root_dir
dw lba_scan_for_filename
dw lba_err
dw lba_noloader
 
get_next_cluster:
; in: ax = cluster
; out: if there is next cluster: CF=1, ax = next cluster
; out: if there is no next cluster: CF=0
push si
cmp [fat_type], 0
jnz gnc16
; for FAT12
push ds
push 0x6000
pop ds
mov si, ax
shr si, 1
add si, ax
test al, 1
lodsw
jz @f
shr ax, 4
@@:
and ax, 0xFFF
cmp ax, 0xFF7
pop ds si
ret
; for FAT16
gnc16:
; each sector contains 200h bytes = 100h FAT entries
; so ah = # of sector, al = offset in sector
mov si, ax
mov ah, 0
shr si, 8
; calculate segment for this sector of FAT table
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si)
; segment = 6000 + 20*si, offset = 0
push es
push si
shl si, 5
add si, 0x6000
mov es, si
pop si
cmp byte [ss:0x8200+si], ah ; sector already loaded?
jnz @f
; load corresponding sector
pusha
push es
xor bx, bx
mov ax, [BPB_RsvdSecCnt]
xor dx, dx
add ax, si
adc dx, bx
mov cx, 1 ; read 1 sector
call [read_sectors]
pop es
popa
@@:
mov si, ax
add si, si
; mov ax, [es:si]
lods word [es:si]
pop es
cmp ax, 0xFFF7
pop si
ret
 
if $ > 0x8000
error 'get_next_cluster must fit in first sector of kordldr.f1x!'
end if
 
load_file:
; in: ss:bp = 0:7C00
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; ASCIIZ name
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found
; out: dx:ax = file size (0xFFFFFFFF if file not found)
xor ax, ax ; start from root directory
mov dx, -1
mov word [filesize], dx
mov word [filesize+2], dx ; initialize file size with invalid value
lea si, [di+6]
parse_dir_loop:
; convert name to FAT name
push di
push ax
push ss
pop es
; convert ASCIIZ filename to FAT name
mov di, filename
push di
mov cx, 8+3
mov al, ' '
rep stosb
pop di
mov cl, 8 ; 8 symbols per name
mov bl, 1
nameloop:
lodsb
test al, al
jz namedone
cmp al, '/'
jz namedone
cmp al, '.'
jz namedot
dec cx
js badname
cmp al, 'a'
jb @f
cmp al, 'z'
ja @f
sub al, 'a'-'A'
@@:
stosb
jmp nameloop
namedot:
inc bx
jp badname
add di, cx
mov cl, 3
jmp nameloop
badname: ; do not make direct js/jp to notfound_pop:
; this generates long forms of conditional jumps and results in longer code
jmp notfound_pop
namedone:
; scan directory
pop ax ; ax = cluster of directory or 0 for root
push ds
push si
push es
pop ds
mov si, filename ; ds:si -> filename in FAT style
test ax, ax
jnz lookup_in_notroot_dir
; for root directory, use the subroutine from bootsector
call [lookup_in_root_dir]
jmp lookup_done
lookup_in_notroot_dir:
; for other directories, read a folder sector-by-sector and scan
; first, try to use the cache
push ds
push cs
pop ds
mov bx, [cachelimit]
add bx, bx
mov di, foldcache_mark
@@:
mov dx, [foldcache_clus+di-foldcache_mark+bx]
cmp dx, ax
jz cacheok
test dx, dx
jz cacheadd ; the cache has place for new entry
dec bx
dec bx
jns @b
; the folder is not present in the cache, so add it
; the cache is full; find the oldest entry and replace it with the new one
mov dx, [cachelimit]
@@:
inc bx
inc bx
cmp word [di+bx], dx ; marks have values 0 through [cachelimit]
jnz @b
cacheadd:
or word [di+bx], 0xFFFF ; very big value, it will be changed soon
mov [foldcache_clus+di-foldcache_mark+bx], ax
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet
cacheok:
; update cache marks
mov dx, [di+bx]
mov cx, [foldcache_size+di-foldcache_mark+bx]
mov di, [cachelimit]
add di, di
cacheupdate:
cmp [foldcache_mark+di], dx
adc [foldcache_mark+di], 0
dec di
dec di
jns cacheupdate
and [foldcache_mark+bx], 0
; done, bx contains (position in cache)*2
pop ds
; mov dx, bx
; shl dx, 8 ; dx = (position in cache)*0x2000/0x10
; add dx, 0x9200
lea dx, [bx+0x92]
xchg dl, dh
mov es, dx
jcxz not_in_cache
call [scan_for_filename]
jz lookup_done
not_in_cache:
; cache miss, read folder data from disk
mov bx, cx
shr bx, 4
shl cx, 5
mov di, cx ; es:di -> free space in cache entry
; external loop: scan clusters
folder_next_cluster:
; internal loop: scan sectors in cluster
mov cx, [sect_per_clus]
push ax
dec ax
dec ax
mul cx
add ax, [bp-8]
adc dx, [bp-6] ; dx:ax = absolute sector
folder_next_sector:
; skip first bx sectors
dec bx
jns folder_skip_sector
push cx
push es di
push 0x8000
pop es
xor bx, bx
mov cx, 1
push es
call [read_sectors]
; copy data to the cache...
pop ds
pop di es
cmp di, 0x2000 ; ...if there is free space, of course
jae @f
push si di
mov cx, 0x100
xor si, si
rep movsw
mov di, es
shr di, 8
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache
pop di si
@@:
push es
push 0x8000
pop es
push cs
pop ds
mov cx, 0x10
call [scan_for_filename]
pop es
pop cx
jz lookup_done_pop
folder_skip_sector:
inc ax
jnz @f
inc dx
@@:
loop folder_next_sector
pop ax ; ax = current cluster
call get_next_cluster
jc folder_next_cluster
stc
push ax
lookup_done_pop:
pop ax
lookup_done:
pop si
pop ds
; CF=1 <=> failed
jnc found
notfound:
pop di
mov bx, 2 ; file not found
mov ax, 0xFFFF
mov dx, ax ; invalid file size
ret
notfound_pop:
pop ax
jmp notfound
found:
mov ax, [es:di+26] ; get cluster
test byte [es:di+11], 10h ; directory?
jz regular_file
cmp byte [si-1], 0
jz notfound ; don't read directories as a regular files
; ok, we have found a directory and the caller requested a file into it
pop di
jmp parse_dir_loop ; restart with new cluster in ax
regular_file:
cmp byte [si-1], 0
jnz notfound ; file does not contain another files
; ok, we have found a regular file and the caller requested it
; save file size
mov dx, [es:di+28]
mov [filesize], dx
mov dx, [es:di+30]
mov [filesize+2], dx
pop di
mov si, [di+4]
shl si, 3
push si ; [ds:di+4] = limit in 4K blocks
les bx, [di] ; es:bx -> buffer
clusloop:
; ax = first cluster, top of stack contains limit in sectors
mov si, ax ; remember current cluster
xor cx, cx ; cx will contain number of consecutive clusters
mov word [cur_delta], cx
mov word [cur_delta+2], cx
mov di, ax
clusfind:
inc di
inc cx
call get_next_cluster
jnc clusread
cmp ax, di
jz clusfind
stc
clusread:
pop di ; limit in sectors
push ax ; save next cluster
pushf ; save flags
; read cx clusters, starting from si
; calculate number of sectors
xchg ax, cx
mul [sect_per_clus]
; dx:ax = number of sectors; compare with limit
mov word [num_sectors], ax
mov word [num_sectors+2], dx
jmp @f
continue_load_file:
les bx, [di] ; es:bx -> buffer
mov di, [di+4] ; ds:di = limit in 4K blocks
shl di, 3 ; now di = limit in sectors
mov ax, word [num_sectors]
mov dx, word [num_sectors+2]
mov si, [cur_cluster]
push [next_cluster]
push [flags]
or ax, dx
jz nextclus
@@:
test dx, dx
jnz clusdecrease
push dx ; limit was not exceeded
cmp ax, di
jbe @f
pop ax
clusdecrease:
push 1 ; limit was exceeded
mov ax, di
@@:
sub di, ax ; calculate new limit
sub word [num_sectors], ax
sbb word [num_sectors+2], 0
; calculate starting sector
xchg ax, cx
lea ax, [si-2]
mul [sect_per_clus]
add ax, word [cur_delta]
adc dx, word [cur_delta+2]
add word [cur_delta], cx
adc word [cur_delta+2], 0
; read
call [read_sectors2]
pop dx
; next cluster?
nextclus:
popf
pop ax
mov [cur_cluster], si
mov [next_cluster], ax
pushf
pop [flags]
jnc @f ; no next cluster => return
mov dl, 1 ; dh=0 in any case
test di, di
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded
push di
jmp clusloop ; all is ok, continue
hooked_err:
mov sp, 7C00h-12-2 ; restore stack
mov dx, 3 ; return: read error
@@:
mov bx, dx
mov ax, [filesize]
mov dx, [filesize+2]
ret
 
; Callback function for secondary loader
callback:
; in: ax = function number; only functions 1 and 2 are defined for now
; save caller's stack
mov dx, ss
mov cx, sp
; set our stack (required because we need ss=0)
xor si, si
mov ss, si
mov sp, 7C00h-8
mov bp, 7C00h
push dx
push cx
; call our function
stc ; unsupported function
dec ax
jz callback_readfile
dec ax
jnz callback_ret
; function 2: continue loading file
; can be called only after function 1 returned value bx=1 (only part of file was loaded)
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error
; out: dx:ax = file size
call continue_load_file
jmp callback_ret_succ
callback_readfile:
; function 1: read file
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; ASCIIZ name
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error
; out: dx:ax = file size (0xFFFFFFFF if file was not found)
call load_file
callback_ret_succ:
clc ; function is supported
callback_ret:
; restore caller's stack
pop cx
pop ss
mov sp, cx
; return to caller
retf
 
secondary_loader_info:
dw 0, 0x1000
dw 0x30000 / 0x1000
db 'kord/loader',0
aKernelNotFound db 'Fatal error: cannot load the secondary loader',0
 
foldcache_clus dw 0,0,0,0,0,0,0 ; start with no folders in cache
foldcache_mark rw 7
foldcache_size rw 7
filename rb 11
if $ > 0x8200
error:
table overwritten
end if
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/fat1x/build.bat
0,0 → 1,3
@fasm -m 65535 bootsect.asm bootsect.bin
@fasm -m 65535 kordldr.f1x.asm kordldr.f1x
@pause
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/fat1x
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/fat32/bootsect.txt
0,0 → 1,333
; Copyright (c) 2008-2009, diamond
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the <organization> nor the
; names of its contributors may be used to endorse or promote products
; derived from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;*****************************************************************************
 
Читай между строк - там никогда не бывает опечаток.
 
Бутсектор для FAT32-тома на носителе с размером сектора 0x200 = 512 байт.
 
=====================================================================
 
Есть две версии в зависимости от того, поддерживает ли носитель LBA,
выбор осуществляется установкой константы use_lba в первой строке исходника.
Требования для работы:
1) Сам бутсектор, первая копия FAT и все используемые файлы
должны быть читабельны. (Если дело происходит на носителе с разбиением на
разделы и загрузочный код в MBR достаточно умный, то читабельности резервной
копии бутсектора (сектор номер 6 на томе) достаточно вместо читабельности
самого бутсектора).
2) Минимальный процессор - 80386.
3) В системе должно быть как минимум 584K свободной базовой памяти.
 
=====================================================================
 
Документация в тему (ссылки проверялись на валидность 15.05.2008):
официальная спецификация FAT: http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
в формате PDF: http://staff.washington.edu/dittrich/misc/fatgen103.pdf
русский перевод: http://wasm.ru/docs/11/fatgen103-rus.zip
официальная спецификация расширения EDD BIOS 3.0: http://www.phoenix.com/NR/rdonlyres/19FEBD17-DB40-413C-A0B1-1F3F560E222F/0/specsedd30.pdf
то же, версия 1.1: http://www.phoenix.com/NR/rdonlyres/9BEDED98-6B3F-4DAC-BBB7-FA89FA5C30F0/0/specsedd11.pdf
описание функций BIOS: Interrupt List by Ralf Brown: http://www.cs.cmu.edu/~ralf/files.html
официальная спецификация Boot BIOS: http://www.phoenix.com/NR/rdonlyres/56E38DE2-3E6F-4743-835F-B4A53726ABED/0/specsbbs101.pdf
 
=====================================================================
 
Схема используемой памяти:
...-7C00 стек
7C00-7E00 код бутсектора
7E00-8200 вспомогательный файл загрузчика (kordldr.f32)
8400-8C00 информация о кэше для таблицы FAT: 100h входов по 8
байт: 4 байта (две ссылки - вперёд и назад) для
организации L2-списка всех прочитанных секторов в
порядке возрастания последнего времени использования
+ 4 байта для номера сектора; при переполнении кэша
выкидывается элемент из головы списка, то есть тот,
к которому дольше всех не было обращений
60000-80000 кэш для таблицы FAT (100h секторов)
80000-90000 текущий кластер текущей рассматриваемой папки
90000-... кэш для содержимого папок (каждой папке отводится
2000h байт = 100h входов, одновременно в кэше
может находиться не более 8 папок;
точный размер определяется размером доступной
физической памяти - как правило, непосредственно
перед A0000 размещается EBDA, Extended BIOS Data Area)
 
=====================================================================
 
Основной процесс загрузки.
Точка входа (start): получает управление от BIOS при загрузке, при этом
dl содержит идентификатор диска, с которого идёт загрузка
1. Настраивает стек ss:sp = 0:7C00 (стек располагается непосредственно перед
кодом), сегмент данных ds = 0, и устанавливает ss:bp на начало
бутсектора (в дальнейшем данные будут адресоваться через [bp+N] -
это освобождает ds и экономит на размере кода). Сохраняет в стеке
идентификатор загрузочного диска для последующего обращения
через byte [bp-2].
2. LBA-версия: проверяет, поддерживает ли носитель LBA, вызовом функции 41h
прерывания 13h. Если нет, переходит на код обработки ошибок с
сообщением об отсутствии LBA.
CHS-версия: определяет геометрию носителя вызовом функции 8 прерывания 13h и
записывает полученные данные поверх BPB. Если вызов завершился ошибкой,
предполагает уже существующие данные корректными.
3. Вычисляет начало данных FAT-тома, сохраняет его в стек для последующего
обращения через dword [bp-10]. В процессе вычисления узнаёт начало
первой FAT, сохраняет и его в стек для последующего обращения через
dword [bp-6].
4. (Заканчивая тему параметров в стеке) Помещает в стек dword-значение -1
для последующего обращения через dword [bp-14] - инициализация
переменной, содержащей текущий сектор, находящийся в кэше FAT
(-1 не является валидным значением для номера сектора FAT).
5. Ищет в корневой папке элемент kordldr.f32. Если не находит - переходит на
код обработки ошибок с сообщением о ненайденном загрузчике.
Замечание: на этом этапе загрузки искать можно только в корневой
папке и только имена, заданные в формате файловой системе FAT
(8+3 - 8 байт на имя, 3 байта на расширение, все буквы должны
быть заглавными, при необходимости имя и расширение дополняются
пробелами, разделяющей точки нет, завершающего нуля нет).
6. Загружает первый кластер файла kordldr.f32 по адресу 0:7E00 и передаёт
ему управление. При этом в регистре eax оказывается абсолютный
номер первого сектора kordldr.f32, а в cx - число считанных секторов
(равное размеру кластера).
 
Вспомогательные процедуры бутсектора.
Код обработки ошибок (err):
1. Выводит строку с сообщением об ошибке.
2. Выводит строку "Press any key...".
3. Ждёт нажатия any key.
4. Вызывает int 18h, давая шанс BIOSу попытаться загрузиться откуда-нибудь ещё.
5. Для подстраховки зацикливается.
 
Процедура чтения кластера (read_cluster):
на входе должно быть установлено:
ss:bp = 0:7C00
es:bx = указатель на начало буфера, куда будут прочитаны данные
eax = номер кластера
на выходе: ecx = число прочитанных секторов (размер кластера),
es:bx указывает на конец буфера, в который были прочитаны данные,
eax и старшие слова других 32-битных регистров разрушаются
Загружает в ecx размер кластера, перекодирует номер кластера в номер сектора
и переходит к следующей процедуре.
 
Процедура чтения секторов (read_sectors32 и read_sectors2):
на входе должно быть установлено:
ss:bp = 0:7C00
es:bx = указатель на начало буфера, куда будут прочитаны данные
eax = стартовый сектор (относительно начала логического диска
для read_sectors32, относительно начала данных
для read_sectors2)
cx = число секторов (должно быть больше нуля)
на выходе: es:bx указывает на конец буфера, в который были прочитаны данные
старшие слова 32-битных регистров могут разрушиться
0. Если вызывается read_sectors2, она переводит указанный ей номер сектора
в номер относительно начала логического диска, прибавляя номер сектора
начала данных, хранящийся в стеке как [bp-10].
1. Переводит стартовый сектор (отсчитываемый от начала тома) в сектор на
устройстве, прибавляя значение соответствующего поля из BPB.
2. В цикле (шаги 3-6) читает секторы, следит за тем, чтобы на каждой итерации
CHS-версия: все читаемые секторы были на одной дорожке.
LBA-версия: число читаемых секторов не превосходило 7Fh (требование
спецификации EDD BIOS).
CHS-версия:
3. Переводит абсолютный номер сектора в CHS-систему: сектор рассчитывается как
единица плюс остаток от деления абсолютного номера на число секторов
на дорожке; дорожка рассчитывается как остаток от деления частного,
полученного на предыдущем шаге, на число дорожек, а цилиндр - как
частное от этого же деления. Если число секторов для чтения больше,
чем число секторов до конца дорожки, уменьшает число секторов для
чтения.
4. Формирует данные для вызова int 13h (ah=2 - чтение, al=число секторов,
dh=головка, (младшие 6 бит cl)=сектор,
(старшие 2 бита cl и весь ch)=дорожка, dl=диск, es:bx->буфер).
5. Вызывает BIOS. Если BIOS рапортует об ошибке, выполняет сброс диска
и повторяет попытку чтения, всего делается не более трёх попыток
(несколько попыток нужно в случае дискеты для гарантии того, что
мотор раскрутился). Если все три раза происходит ошибка чтения,
переходит на код обработки ошибок с сообщением "Read error".
6. В соответствии с числом прочитанных на текущей итерации секторов
корректирует текущий сектор, число оставшихся секторов и указатель на
буфер (в паре es:bx корректируется es). Если всё прочитано, заканчивает
работу, иначе возвращается на шаг 3.
LBA-версия:
3. Если число секторов для чтения больше 7Fh, уменьшает его (для текущей
итерации) до 7Fh.
4. Формирует в стеке пакет для int 13h (кладёт все нужные данные командами
push, причём в обратном порядке: стек - структура LIFO, и данные в
стеке хранятся в обратном порядке по отношению к тому, как их туда
клали).
5. Вызывает BIOS. Если BIOS рапортует об ошибке, переходит на код обработки
ошибок с сообщением "Read error". Очищает стек от пакета,
сформированного на предыдущем шаге.
6. В соответствии с числом прочитанных на текущей итерации секторов
корректирует текущий сектор, число оставшихся секторов и указатель на
буфер (в паре es:bx корректируется es). Если всё прочитано, заканчивает
работу, иначе возвращается на шаг 3.
 
Процедура поиска элемента в папке (lookup_in_dir):
на входе должно быть установлено:
ss:bp = 0:7C00
ds:si = указатель на имя файла в формате FAT (см. выше)
eax = начальный кластер папки
bx = 0
на выходе: флаг CF определяет, удалось ли найти файл; если удалось, то
CF сброшен и es:di указывает на элемент папки
В цикле считывает кластеры папки и ищет запрошенный элемент в прочитанных
данных. Для чтения кластера использует уже описанную процедуру read_clusters,
для продвижения по цепочке кластеров - описанную далее процедуру
get_next_clusters. Данные читаются в область памяти, начинающуюся с адреса
8000:0000, при этом первые 2000h байт из данных папки (может быть, меньше,
если чтение прервётся раньше) не перекрываются последующими чтениями
(это будет использовано позднее, в системе кэширования из kordldr.f32).
Выход осуществляется в любом из следующих случаев: найден запрошенный элемент;
кончились элементы в папке (первый байт очередного элемента нулевой);
кончились данные папки в соответствии с цепочкой кластеров из FAT.
 
Процедура вывода на экран ASCIIZ-строки (out_string):
на входе: ds:si -> строка
В цикле, пока не достигнут завершающий ноль, вызывает функцию int 10h/ah=0Eh.
 
=====================================================================
 
Работа вспомогательного загрузчика kordldr.f32:
1. Определяет, был ли он загружен CHS- или LBA-версией бутсектора.
В зависимости от этого устанавливает смещения используемых процедур
бутсектора. Критерий проверки: в CHS-версии по адресу err находится
байт 0xE8 (машинная команда call), в LBA-версии по тому же адресу
находится байт 0x14, а адрес процедуры err другой.
2. Узнаёт размер свободной базовой памяти (т.е. свободного непрерывного куска
адресов памяти, начинающегося с 0) вызовом int 12h. В соответствии с
ним вычисляет число элементов в кэше папок. Хотя бы для одного элемента
место должно быть, отсюда ограничение в 592 Kb (94000h байт).
Замечание: этот размер не может превосходить 0A0000h байт и
на практике оказывается немного (на 1-2 килобайта) меньшим из-за
наличия дополнительной области данных BIOS "вверху" базовой памяти.
3. Инициализирует кэширование папок. Бутсектор уже загрузил какую-то часть
данных корневой папки; копирует загруженные данные в кэш и запоминает,
что в кэше есть корневая папка.
4. Инициализирует кэширование FAT. Бутсектор имеет дело с FAT в том и только
том случае, когда ему приходится загружать данные корневой папки,
не поместившиеся в один кластер. В этом случае в памяти присутствует
один сектор FAT (если было несколько обращений - последний из
использованных).
5. Если кластер равен сектору, то бутсектор загрузил только часть файла
kordldr.f32, и загрузчик подгружает вторую свою часть, используя
значения регистров на входе в kordldr.f32.
6. Загружает вторичный загрузчик kord/loader по адресу 1000:0000. Если файл не
найден, или оказался папкой, или оказался слишком большим, то переходит
на код обработки ошибок из бутсектора с сообщением
"Fatal error: cannot load the secondary loader".
Замечание: на этом этапе имя файла уже можно указывать вместе с путём
и в формате ASCIIZ, хотя поддержки длинных имён и неанглийских символов
по-прежнему нет.
7. Изменяет код обработки ошибок бутсектора на переход на метку hooked_err.
Это нужно, чтобы последующие обращения к коду бутсектора в случае
ошибок чтения не выводил соответствующее сообщение с последующей
перезагрузкой, а рапортовал об ошибке чтения, которую могло бы
как-нибудь обработать ядро.
8. Если загрузочный диск имеет идентификатор меньше 0x80,
то устанавливает al='f' ("floppy"), ah=идентификатор диска,
иначе al='h' ("hard"), ah=идентификатор диска-0x80 (номер диска).
(Говорите, дискеток с FAT32 не бывает? В чём-то Вы правы... но
уверены ли Вы, что нет загрузочных устройств, подобных дискетам,
но большего размера, и для которых BIOS-идентификатор меньше 0x80?)
Устанавливает bx='32' (тип файловой системы - FAT32).
Устанавливает si=смещение функции обратного вызова. Поскольку в этот
момент ds=0, то ds:si образуют полный адрес.
9. Передаёт управление по адресу 1000:0000.
 
Функция обратного вызова для вторичного загрузчика:
предоставляет возможность чтения файла.
Вход и выход описаны в спецификации на загрузчик.
1. Сохраняет стек вызывающего кода и устанавливает свой стек:
ss:sp = 0:(7C00-10), bp=7C00: пара ss:bp при работе с остальным
кодом должна указывать на 0:7C00, а -10 берётся от того, что
инициализирующий код бутсектора уже поместил в стек 10 байт параметров,
и они должны сохраняться в неизменности. (Значение [ebp-14],
"текущий сектор, находящийся в кэше FAT", не используется после
инициализации кэширования в kordldr.f32.)
2. Разбирает переданные параметры и вызывает нужную из вспомогательных
процедур (загрузки файла либо продолжения загрузки файла).
3. Восстанавливает стек вызывающего кода и возвращает управление.
 
Вспомогательные процедуры kordldr.f32.
Процедура получения следующего кластера в FAT (get_next_cluster):
1. Вычисляет номер сектора в FAT, в котором находится запрошенный элемент.
(В секторе 0x200 байт, каждый вход занимает 4 байта.)
2. Проверяет, есть ли сектор в кэше. Если есть, пропускает шаги 3 и 4.
3. Если нет, то в кэш нужно вставить новый элемент. Если кэш ещё не заполнен,
выделяет очередной элемент в конце кэша. Если заполнен, удаляет
самый старый элемент (тот, к которому дольше всего не было обращений);
для того, чтобы отслеживать порядок элементов по времени последнего
обращения, все (выделенные) элементы кэша связаны в двусвязный список,
в котором первым элементом является самый старый, а ссылки вперёд
указывают на следующий по времени последнего обращения.
4. Читает соответствующий сектор FAT с диска.
5. Корректирует список: текущий обрабатываемый элемент удаляется с той позиции,
где он находится, и добавляется в конец. (В случае со свежедобавленными
в кэш элементами удаления не делается, поскольку их в списке ещё нет.)
6. Считывает нужный вход в FAT, сбрасывая старшие 4 бита.
7. Сравнивает прочитанное значение с пределом: если оно строго меньше
0x0FFFFFF7, то оно задаёт номер следующего кластера в цепочке;
в противном случае цепочка закончилась.
 
Процедура загрузки файла (load_file):
1. Текущая рассматриваемая папка - корневая. В цикле выполняет шаги 2-4.
2. Конвертирует имя текущего рассматриваемого компонента имени (компоненты
разделяются символом '/') в FAT-формат 8+3. Если это невозможно
(больше 8 символов в имени, больше 3 символов в расширении или
больше одной точки), возвращается с ошибкой.
3. Ищет элемент с таким именем в текущей рассматриваемой папке.
а) Проверяет, есть ли такая папка в кэше папок. (Идентификация папок
осуществляется по номеру начального кластера.) Если такой папки ещё
нет, добавляет её в кэш; если тот переполняется, выкидывает папку,
к которой дольше всего не было обращений. (Для каждого элемента кэша
хранится метка от 0 до (размер кэша)-1, определяющая его номер при
сортировке по давности последнего обращения. При обращении к какому-то
элементу его метка становится нулевой, а те метки, которые меньше
старого значения, увеличиваются на единицу.)
б) Просматривает в поисках запрошенного имени все элементы из кэша,
используя процедуру из бутсектора. Если обнаруживает искомый элемент,
переходит к шагу 4. Если обнаруживает конец папки, возвращается из
процедуры с ошибкой.
в) В цикле считывает папку посекторно. При этом пропускает начальные
секторы, которые уже находятся в кэше и уже были просмотрены. Каждый
прочитанный сектор копирует в кэш, если там ещё остаётся место,
и просматривает в нём все элементы. Работает, пока не случится одно из
трёх событий: найден искомый элемент; кончились кластеры (судя по
цепочке кластеров в FAT); очередной элемент папки сигнализирует о конце
(первый байт нулевой). В двух последних случаях возвращается с ошибкой.
4. Проверяет тип найденного элемента (файл/папка): последний элемент в
запрошенном имени должен быть файлом, все промежуточные - папками.
Если текущий компонент имени - промежуточный, продвигает текущую
рассматриваемую папку и возвращается к пункту 2.
5. Проходит по цепочке кластеров в FAT и считывает все кластеры в указанный
при вызове буфер последовательными вызовами функции бутсектора;
при этом если несколько кластеров файла расположены на диске
последовательно, то их чтение объединяется в одну операцию.
Следит за тем, чтобы не превысить указанный при вызове процедуры
лимит числа секторов для чтения.
 
Процедура продолжения загрузки файла (continue_load_file): встроена
внутрь шага 5 load_file; загружает в регистры нужные значения (ранее
сохранённые из load_file) и продолжает шаг 5.
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/fat32/kordldr.f32.asm
0,0 → 1,672
; 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
push ss
pop ds
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
push es
pushad
lea cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-3))] ; +0x10000 - for FASM
shl cx, 9-3
mov es, cx
xor bx, bx
mov cx, 1
add eax, [bp-6] ; FAT start
sub eax, [bp-10]
call [read_sectors2]
popad
pop es
@@:
; 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-3))]
pop di
and di, 0x7F
shl di, 2
shl ax, 9-3
mov ds, ax
and byte [di+3], 0x0F
mov eax, [di]
pop 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 ; 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-14-2 ; restore stack
mov dx, 3 ; return: read error
@@:
mov bx, dx
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 'kord/loader',0
aKernelNotFound db 'Fatal error: cannot load the secondary loader',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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/fat32/build.bat
0,0 → 1,3
@fasm -m 65535 bootsect.asm bootsect.bin
@fasm -m 65535 kordldr.f32.asm kordldr.f32
@pause
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/fat32
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/mkfloppy.inc
0,0 → 1,91
; ---------------------------------------------------------------------------
; mkfloppy.inc
; ---------------------------------------------------------------------------
; Created by Phantom-84
; ---------------------------------------------------------------------------
 
FA_RO equ 01h
FA_HID equ 02h
FA_SYS equ 04h
FA_VOL equ 08h
FA_DIR equ 10h
FA_ARC equ 20h
 
DSTAMP equ 28C1h
TSTAMP equ 6000h
 
root_size=0
 
macro reset id
{
local count, cur, disp, val, var
times 511-($+511) mod 512 db 0
if id#_size>0
count=(id#_size+511)/512
cur=id#_base/512-(33-2)
repeat count
if %=count
val=0FFFh
else
val=cur+1
end if
if cur and 1
val=val shl 4
end if
disp=(cur*3)/2
load var word from 512+disp
var=var or val
store word var at 512+disp
store word var at 10*512+disp
cur=cur+1
end repeat
end if
}
 
macro dent id, name, attr
{
@@ db name
times @b+11-$ db 32
db attr
dw 0, TSTAMP, DSTAMP, DSTAMP, 0, TSTAMP, DSTAMP
if id#_size=0
dw 0
else
dw id#_base/512-(33-2)
end if
if (attr) and FA_DIR
dd 0
else
dd id#_size
end if
}
 
macro orgdir id, parentid
{
id#_base:
dent id, ".", FA_DIR
dent parentid, "..", FA_DIR
}
 
macro findir id
{
id#_size=$-id#_base
reset id
}
 
macro stod id, parentid
{
orgdir id, parentid
id
findir id
}
 
macro stof id, name
{
id#_base:
file name
id#_size=$-id#_base
reset id
}
 
defdir fix macro
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/build.bat
0,0 → 1,20
echo off
cls
echo ** bulding after win loader **
@fasm -m 65535 after_win/kordldr.win.asm after_win/kordldr.win
echo ==============================
echo ** building first loader for cd/dvd **
@fasm -m 65535 cdfs/bootsect.asm cdfs/bootsect.bin
echo ==============================
echo ** building first loader for fat12/fat16 **
@fasm -m 65535 fat1x/bootsect.asm fat1x/bootsect.bin
@fasm -m 65535 fat1x/kordldr.f1x.asm fat1x/kordldr.f1x
echo ==============================
echo ** building firs loader for fat32 **
@fasm -m 65535 fat32/bootsect.asm fat32/bootsect.bin
@fasm -m 65535 fat32/kordldr.f1x.asm fat32/kordldr.f1x
echo ==============================
echo ** make a image of fdd **
@fasm -m 65535 floppy.asc kord.img
 
@pause
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot/floppy.asc
0,0 → 1,49
include "mkfloppy.inc"
;// insert boot sect
file "fat1x/bootsect.bin", 512
 
; fat1
db 0F0h, 0FFh, 0FFh, 9*512-3 dup 0
; fat2
db 0F0h, 0FFh, 0FFh, 9*512-3 dup 0
 
; root
dent kordldr, "KORDLDR F1X", FA_ARC
dent kord, "KORD ",FA_DIR
dent kolibri, "KOLIBRI ",FA_DIR
; ...
 
rb 33*512-$
;///////////////////////////
defdir kord
{
dent loader, "LOADER ", FA_ARC
dent ini,"STARTOS INI", FA_ARC
}
 
defdir kolibri
{
dent kolibri_ldm, "KOLIBRI LDM", FA_ARC
}
 
 
; data
stof kordldr, "fat1x/kordldr.f1x"
stod kord,root
 
stof loader, "../loader"
stof ini,"../startos.ini"
 
store dword ini_base/512+1 at ini_base+1F8h
store word (ini_size+511)/512-1 at ini_base+1FCh
store word 220h at ini_base+1FEh
 
stod kolibri,root
stof kolibri_ldm, "../kolibri_ldm/bin/kolibri.ldm"
store dword kolibri_ldm_base/512+1 at kolibri_ldm_base+1F8h
store word (kolibri_ldm_size+511)/512-1 at kolibri_ldm_base+1FCh
store word 220h at kolibri_ldm_base+1FEh
 
 
; ...
rb 2*80*18*512-$
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/loader.lst
0,0 → 1,2147
flat assembler version 1.68 (65535 kilobytes memory)
0000: E9 E1 0A jmp start
0003: 53 65 63 6F 6E 64 61 72 79 20 4C 6F 61 version db 'Secondary Loader v 0.009', 0
0010: 64 65 72 20 76 20 30 2E 30 30 39 00
001C: 53 65 6C 65 63 74 20 73 65 63 74 69 6F select_section db 'Select section:'
0029: 6E 3A
002B: 53 65 63 74 69 6F 6E 20 64 65 73 63 72 section_description db 'Section description:'
0038: 69 70 74 69 6F 6E 3A
003F: 53 6F 66 74 20 28 63 29 20 32 30 30 38 soft_mes db 'Soft (c) 2008'
004C: 3E 46 61 74 61 6C 20 2D 20 43 50 55 20 badprocessor db '>Fatal - CPU 586+ required.', 0
0059: 35 38 36 2B 20 72 65 71 75 69 72 65 64
0066: 2E 00
0068: 3E 45 72 72 6F 72 3A 20 63 61 6E 6E 6F error_ini_f1 db '>Error: cannot load ini file, buffer is full', 0
0075: 74 20 6C 6F 61 64 20 69 6E 69 20 66 69
0082: 6C 65 2C 20 62 75 66 66 65 72 20 69 73
008F: 20 66 75 6C 6C 00
0095: 3E 45 72 72 6F 72 3A 20 69 6E 69 20 66 error_ini_f2 db '>Error: ini file not found', 0
00A2: 69 6C 65 20 6E 6F 74 20 66 6F 75 6E 64
00AF: 00
00B0: 3E 45 72 72 6F 72 3A 20 63 61 6E 6E 6F error_ini_f3 db '>Error: cannot read ini file', 0
00BD: 74 20 72 65 61 64 20 69 6E 69 20 66 69
00CA: 6C 65 00
00CD: 3E 45 72 72 6F 72 3A 20 75 6E 72 65 63 error_ini_nf db '>Error: unrecognized error when loading ini file', 0
00DA: 6F 67 6E 69 7A 65 64 20 65 72 72 6F 72
00E7: 20 77 68 65 6E 20 6C 6F 61 64 69 6E 67
00F4: 20 69 6E 69 20 66 69 6C 65 00
00FE: 3E 4E 6F 74 20 66 6F 75 6E 64 20 73 65 not_found_sec_loader db '>Not found section [loader]', 0
010B: 63 74 69 6F 6E 20 5B 6C 6F 61 64 65 72
0118: 5D 00
011A: 3E 4E 6F 74 20 66 6F 75 6E 64 20 76 61 not_found_def_sect db '>Not found value default in section [loader]', 0
0127: 6C 75 65 20 64 65 66 61 75 6C 74 20 69
0134: 6E 20 73 65 63 74 69 6F 6E 20 5B 6C 6F
0141: 61 64 65 72 5D 00
0147: 3E 45 72 72 6F 72 20 69 6E 20 73 65 63 default_eq_loader db '>Error in section [loader] parametr default=loader', 0
0154: 74 69 6F 6E 20 5B 6C 6F 61 64 65 72 5D
0161: 20 70 61 72 61 6D 65 74 72 20 64 65 66
016E: 61 75 6C 74 3D 6C 6F 61 64 65 72 00
017A: 3E 46 6F 75 6E 64 20 65 71 75 61 6C 20 found_equal_default db '>Found equal parametr default will be use first value', 0
0187: 70 61 72 61 6D 65 74 72 20 64 65 66 61
0194: 75 6C 74 20 77 69 6C 6C 20 62 65 20 75
01A1: 73 65 20 66 69 72 73 74 20 76 61 6C 75
01AE: 65 00
01B0: 3E 46 6F 75 6E 64 20 65 71 75 61 6C 20 found_equal_timeout db '>Found equal parametr timeout will be use first value', 0
01BD: 70 61 72 61 6D 65 74 72 20 74 69 6D 65
01CA: 6F 75 74 20 77 69 6C 6C 20 62 65 20 75
01D7: 73 65 20 66 69 72 73 74 20 76 61 6C 75
01E4: 65 00
01E6: 3E 53 65 63 74 69 6F 6E 20 74 69 6D 65 set_default_timeout_val db '>Section timeout has incorrect value, will be use default value', 0
01F3: 6F 75 74 20 68 61 73 20 69 6E 63 6F 72
0200: 72 65 63 74 20 76 61 6C 75 65 2C 20 77
020D: 69 6C 6C 20 62 65 20 75 73 65 20 64 65
021A: 66 61 75 6C 74 20 76 61 6C 75 65 00
0226: 3E 49 20 77 69 6C 6C 20 75 73 65 20 70 error_ini_common db '>I will use predefined settings and try to boot. Let's hope for the best...'
0233: 72 65 64 65 66 69 6E 65 64 20 73 65 74
0240: 74 69 6E 67 73 20 61 6E 64 20 74 72 79
024D: 20 74 6F 20 62 6F 6F 74 2E 20 4C 65 74
025A: 27 73 20 68 6F 70 65 20 66 6F 72 20 74
0267: 68 65 20 62 65 73 74 2E 2E 2E
0271: 0D 0A 50 72 65 73 73 20 61 6E 79 20 6B db 13, 10, 'Press any key to continue...', 0
027E: 65 79 20 74 6F 20 63 6F 6E 74 69 6E 75
028B: 65 2E 2E 2E 00
0290: 3E 49 6E 69 20 66 69 6C 65 20 6C 6F 61 load_ini db '>Ini file loaded successfully', 0
029D: 64 65 64 20 73 75 63 63 65 73 73 66 75
02AA: 6C 6C 79 00
02AE: 3E 45 6E 64 20 70 61 72 73 69 6E 67 20 parse_ini_end db '>End parsing ini file', 0
02BB: 69 6E 69 20 66 69 6C 65 00
02C4: 3E 50 6F 69 6E 74 20 74 6F 20 64 65 66 point_to_default_sec_not_found db '>Point to default section is not found in ini file', 0
02D1: 61 75 6C 74 20 73 65 63 74 69 6F 6E 20
02DE: 69 73 20 6E 6F 74 20 66 6F 75 6E 64 20
02EB: 69 6E 20 69 6E 69 20 66 69 6C 65 00
02F7: 3E 49 6E 63 6F 72 65 63 74 20 73 65 63 incorect_section_define db '>Incorect section define not found ']'', 0
0304: 74 69 6F 6E 20 64 65 66 69 6E 65 20 6E
0311: 6F 74 20 66 6F 75 6E 64 20 27 5D 27 00
031E: 22 53 65 63 74 69 6F 6E 20 75 6E 6E 61 default_section_name db '"Section unname"'
032B: 6D 65 22
032E: 50 72 65 73 73 20 61 6E 79 20 6B 65 79 start_msg db 'Press any key to change default section, press [Enter] to continue booting'
033B: 20 74 6F 20 63 68 61 6E 67 65 20 64 65
0348: 66 61 75 6C 74 20 73 65 63 74 69 6F 6E
0355: 2C 20 70 72 65 73 73 20 5B 45 6E 74 65
0362: 72 5D 20 74 6F 20 63 6F 6E 74 69 6E 75
036F: 65 20 62 6F 6F 74 69 6E 67
0378: 6F 72 20 77 61 69 74 20 34 20 73 65 63 time_msg db 'or wait 4 seconds before default continuation'
0385: 6F 6E 64 73 20 62 65 66 6F 72 65 20 64
0392: 65 66 61 75 6C 74 20 63 6F 6E 74 69 6E
039F: 75 61 74 69 6F 6E
03A5: 73 65 63 6F 6E 64 73 20 62 65 66 6F 72 time_str db 'seconds before default continuation'
03B2: 65 20 64 65 66 61 75 6C 74 20 63 6F 6E
03BF: 74 69 6E 75 61 74 69 6F 6E
03C8: 53 65 74 20 73 74 61 63 6B 20 26 20 73 stack_msg db 'Set stack & segments is have completed', 0
03D5: 65 67 6D 65 6E 74 73 20 69 73 20 68 61
03E2: 76 65 20 63 6F 6D 70 6C 65 74 65 64 00
03EF: 48 61 76 65 20 6C 6F 61 64 65 64 20 73 show_string db 'Have loaded size:'
03FC: 69 7A 65 3A
0400: 20 20 20 20 20 20 00 show_decode db ' ', 0
0407: 20 20 20 20 20 20 20 2D 4D 65 73 73 61 show_db1 db ' -Message debug1', 0
0414: 67 65 20 64 65 62 75 67 31 00
041E: 20 20 20 20 20 20 20 2D 4D 65 73 73 61 show_db2 db ' -Message debug2', 0
042B: 67 65 20 64 65 62 75 67 32 00
0435: 5B 6C 6F 61 64 65 72 5D 20 69 73 20 66 lm_l_found db '[loader] is found', 0
0442: 6F 75 6E 64 00
0447: 74 69 6D 65 6F 75 74 20 69 73 20 66 6F lm_lf_timeout db 'timeout is found', 0
0454: 75 6E 64 00
0458: 6E 61 6D 65 20 64 65 66 61 75 6C 74 20 lm_lf_default db 'name default is found and end parsing section', 0
0465: 69 73 20 66 6F 75 6E 64 20 61 6E 64 20
0472: 65 6E 64 20 70 61 72 73 69 6E 67 20 73
047F: 65 63 74 69 6F 6E 00
0486: 66 6F 75 6E 64 20 73 65 63 74 69 6F 6E lm_lf_section db 'found section [', 0
0493: 20 5B 00
0496: 66 6F 75 6E 64 20 64 65 66 61 75 6C 74 lm_lf_default_f db 'found default parametr', 0
04A3: 20 70 61 72 61 6D 65 74 72 00
04AD: 73 65 63 74 69 6F 6E 20 5B 6C 6F 61 64 lm_l_end db 'section [loader] is end', 0
04BA: 65 72 5D 20 69 73 20 65 6E 64 00
04C5: 53 48 4F 57 20 41 4C 4C 20 53 65 63 74 show_all_sect db 'SHOW ALL Sections', 0
04D2: 69 6F 6E 73 00
04D7: 4E 6F 74 20 73 68 6F 77 20 73 65 63 74 no_show_only_w db 'Not show sections - only work on default sect', 0
04E4: 69 6F 6E 73 20 2D 20 6F 6E 6C 79 20 77
04F1: 6F 72 6B 20 6F 6E 20 64 65 66 61 75 6C
04FE: 74 20 73 65 63 74 00
0505: 5B 20 6E 6F 74 20 66 6F 75 6E 64 00 _not_found db '[ not found', 0
0511: 5B 5D 20 66 6F 75 6E 64 00 _found_1 db '[] found', 0
051A: 5B 20 66 6F 75 6E 64 00 _found_2 db '[ found', 0
0522: 48 65 6C 6C 6F 20 24 29 00 say_hello db 'Hello $)', 0
052B: 53 74 61 72 74 20 75 73 65 5F 52 61 6D ramdiskFS_st db 'Start use_RamdiskFS macros', 0
0538: 64 69 73 6B 46 53 20 6D 61 63 72 6F 73
0545: 00
0546: 20 20 20 20 20 20 20 2D 4B 62 20 61 76 free_memory_msg db ' -Kb availability system free memory', 0
0553: 61 69 6C 61 62 69 6C 69 74 79 20 73 79
0560: 73 74 65 6D 20 66 72 65 65 20 6D 65 6D
056D: 6F 72 79 00
0571: 20 20 20 20 20 20 20 2D 4B 62 20 65 71 RamdiskSize_msg db ' -Kb equal RamdiskSize', 0
057E: 75 61 6C 20 52 61 6D 64 69 73 6B 53 69
058B: 7A 65 00
058E: 20 20 20 20 20 20 20 20 2D 62 79 74 73 RamdiskSector_msg db ' -byts RamdiskSector', 0
059B: 20 52 61 6D 64 69 73 6B 53 65 63 74 6F
05A8: 72 00
05AA: 20 20 20 20 20 20 20 2D 52 61 6D 64 69 RamdiskCluster_msg db ' -RamdiskCluster', 0
05B7: 73 6B 43 6C 75 73 74 65 72 00
05C1: 20 20 20 20 20 20 20 2D 73 69 7A 65 20 RamdiskFile_msg db ' -size RamdiskFile', 0
05CE: 52 61 6D 64 69 73 6B 46 69 6C 65 00
05DA: 20 20 20 20 20 20 20 2D 66 69 72 73 74 fat_create_msg db ' -first create fat table, point to next block', 0
05E7: 20 63 72 65 61 74 65 20 66 61 74 20 74
05F4: 61 62 6C 65 2C 20 70 6F 69 6E 74 20 74
0601: 6F 20 6E 65 78 74 20 62 6C 6F 63 6B 00
060E: 20 20 20 20 20 20 20 2D 69 6E 20 62 79 BPB_msg db ' -in byte, why we get data from move BPB struct', 0
061B: 74 65 2C 20 77 68 79 20 77 65 20 67 65
0628: 74 20 64 61 74 61 20 66 72 6F 6D 20 6D
0635: 6F 76 65 20 42 50 42 20 73 74 72 75 63
0642: 74 00
0644: 20 20 20 20 20 20 20 2D 66 69 72 73 74 firstDataSect_msg db ' -first data sector, offset to data in sectors', 0
0651: 20 64 61 74 61 20 73 65 63 74 6F 72 2C
065E: 20 6F 66 66 73 65 74 20 74 6F 20 64 61
066B: 74 61 20 69 6E 20 73 65 63 74 6F 72 73
0678: 00
0679: 20 20 20 20 20 20 20 2D 73 69 7A 65 20 size_root_dir_msg db ' -size root dir in sectrors', 0
0686: 72 6F 6F 74 20 64 69 72 20 69 6E 20 73
0693: 65 63 74 72 6F 72 73 00
069B: 20 20 20 20 20 20 20 2D 73 69 7A 65 20 DataClasters_msg db ' -size data in Clasters', 0
06A8: 64 61 74 61 20 69 6E 20 43 6C 61 73 74
06B5: 65 72 73 00
06B9: 20 20 20 20 20 20 20 2D 69 66 20 2D 31 check_name_fat_msg db ' -if -1 name is present, else 0 then not present name', 0
06C6: 20 6E 61 6D 65 20 69 73 20 70 72 65 73
06D3: 65 6E 74 2C 20 65 6C 73 65 20 30 20 74
06E0: 68 65 6E 20 6E 6F 74 20 70 72 65 73 65
06ED: 6E 74 20 6E 61 6D 65 00
06F5: 20 20 20 20 20 20 20 2D 69 66 20 2D 31 convertion_file_name_msg db ' -if -1, then destination name is bad', 0
0702: 2C 20 74 68 65 6E 20 64 65 73 74 69 6E
070F: 61 74 69 6F 6E 20 6E 61 6D 65 20 69 73
071C: 20 62 61 64 00
0721: 2D 4D 61 6B 65 20 46 41 54 31 32 20 52 make_fat12_RFS_msg db '-Make FAT12 Ram FS', 0
072E: 61 6D 20 46 53 00
0734: 2D 45 6E 64 20 6D 61 6B 65 20 52 61 6D get_type_FS_msg db '-End make RamDisk', 0
0741: 44 69 73 6B 00
0746: 20 20 20 20 2D 72 65 74 75 72 6E 20 63 return_code_af_move db ' -return code after 0x87 int 0x15, move block', 0
0753: 6F 64 65 20 61 66 74 65 72 20 30 78 38
0760: 37 20 69 6E 74 20 30 78 31 35 2C 20 6D
076D: 6F 76 65 20 62 6C 6F 63 6B 00
0777: 20 20 20 20 2D 72 65 74 75 72 6E 20 63 return_code_af_fat_m db ' -return code after 0x87 int 0x15, move fat struc', 0
0784: 6F 64 65 20 61 66 74 65 72 20 30 78 38
0791: 37 20 69 6E 74 20 30 78 31 35 2C 20 6D
079E: 6F 76 65 20 66 61 74 20 73 74 72 75 63
07AB: 00
07AC: 5B 6C 6F 61 64 65 72 5D parse_loader db '[loader]'
07B4: 74 69 6D 65 6F 75 74 parse_l_timeout db 'timeout'
07BB: 64 65 66 61 75 6C 74 parse_l_default db 'default'
07C2: 61 6D 65 parse_name db 'ame'
07C5: 64 65 73 63 72 69 70 74 parse_descript db 'descript'
07CD: 4C 6F 61 64 65 72 4D 6F 64 75 6C 65 parse_LoaderModule db 'LoaderModule'
07D9: 52 61 6D 64 69 73 6B 53 69 7A 65 parse_RamdiskSize db 'RamdiskSize'
07E4: 52 61 6D 64 69 73 6B 46 53 parse_RamdiskFS db 'RamdiskFS'
07ED: 52 61 6D 64 69 73 6B 53 65 63 74 6F 72 parse_RamdiskSector db 'RamdiskSector'
07FA: 52 61 6D 64 69 73 6B 43 6C 75 73 74 65 parse_RamdiskCluster db 'RamdiskCluster'
0807: 72
0808: 46 41 54 parse_RFS_FAT db 'FAT'
080B: 4B 52 46 53 parse_RFS_KRFS db 'KRFS'
080F: 4C 6F 61 64 65 72 49 6D 61 67 65 parse_Loader_Image db 'LoaderImage'
081A: 52 61 6D 64 69 73 6B 46 69 6C 65 parse_RamdiskFile db 'RamdiskFile'
0825: 66 39 C8 cmp eax, ecx
0828: 72 0D jb @f
082A: 66 31 D2 xor edx, edx
082D: 66 F7 F1 div ecx
0830: 66 52 push edx
0832: E8 F0 FF call decode
0835: 66 58 pop eax
0837: 0C 30 or al, 0x30
0839: 88 05 mov [ ds : di ], al
083B: 47 inc di
083C: C3 ret
083D: B4 0E mov ah, 0Eh
083F: B7 00 mov bh, 0
0841: CD 10 int 10h
0843: C3 ret
0844: 60 pusha
0845: AC lodsb
0846: E8 F4 FF call putchar
0849: AC lodsb
084A: 3C 00 cmp al, 0
084C: 75 F8 jnz @b
084E: B0 0D mov al, 13
0850: E8 EA FF call putchar
0853: B0 0A mov al, 10
0855: E8 E5 FF call putchar
0858: 61 popa
0859: C3 ret
085A: B4 00 mov ah, 0
085C: CD 16 int 16h
085E: 38 D8 cmp al, bl
0860: 72 F8 jb getkey
0862: 38 F8 cmp al, bh
0864: 77 F4 ja getkey
0866: 50 push ax
0867: E8 D3 FF call putchar
086A: 58 pop ax
086B: 83 E0 0F and ax, 0Fh
086E: 75 02 jnz @f
0870: B0 0A mov al, 10
0872: C3 ret
0873: 26 8A 05 mov al, byte [ es : di ]
0876: 47 inc di
0877: 49 dec cx
0878: E3 20 jcxz .exit
087A: 3C 0A cmp al, 0xa
087C: 74 0A jz ._entry
087E: 3C 3B cmp al, ';'
0880: 75 F1 jnz .start
0882: B0 0A mov al, 0xa
0884: F2 repnz
0885: AE scasb
0886: E3 12 jcxz .exit
0888: 26 8A 05 mov al, byte [ es : di ]
088B: 3C 20 cmp al, ' '
088D: 75 07 jnz .not_space
088F: F3 repe
0890: AE scasb
0891: 4F dec di
0892: 41 inc cx
0893: 26 8A 05 mov al, byte [ es : di ]
0896: 3C 3B cmp al, ';'
0898: 74 E8 jz .first_com
089A: C3 ret
089B: 56 push si
089C: 68 00 20 push ini_data_
089F: 07 pop es
08A0: B0 5D mov al, ']'
08A2: F2 repnz
08A3: AE scasb
08A4: 85 C9 test cx, cx
08A6: 0F 84 0F 02 jz error.incorect_section_def
08AA: B0 6E mov al, 'n'
08AC: F2 repnz
08AD: AE scasb
08AE: E3 69 jcxz .not_name_sec_fb
08B0: BE C2 07 mov si, parse_name
08B3: 51 push cx
08B4: 57 push di
08B5: B9 03 00 mov cx, parse_name_e - parse_name
08B8: F3 repe
08B9: A6 cmpsb
08BA: 5F pop di
08BB: 59 pop cx
08BC: 74 02 jz .yaaa_find_value
08BE: EB EC jmp .find_val_name_fb
08C0: 83 E9 03 sub cx, parse_name_e - parse_name
08C3: 83 C7 03 add di, parse_name_e - parse_name
08C6: B8 20 3D mov ax, 0x3d20
08C9: F3 repe
08CA: AE scasb
08CB: 85 C9 test cx, cx
08CD: 74 4A jz .not_name_sec_fb
08CF: 26 3A 65 FF cmp ah, byte [ es : di - 1 ]
08D3: 75 D5 jnz .find_val_name_fb1
08D5: F3 repe
08D6: AE scasb
08D7: 41 inc cx
08D8: 4F dec di
08D9: 06 push es
08DA: 1F pop ds
08DB: 68 00 B8 push 0xb800
08DE: 07 pop es
08DF: 31 C0 xor ax, ax
08E1: B8 20 07 mov ax, 0x0720
08E4: B9 27 00 mov cx, 39
08E7: 89 FE mov si, di
08E9: 89 D7 mov di, dx
08EB: 83 EF 02 sub di, 2
08EE: F3 rep
08EF: AB stosw
08F0: 89 D7 mov di, dx
08F2: B4 0F mov ah, color_sym_white
08F4: B9 24 00 mov cx, 36
08F7: AC lodsb
08F8: 83 EF 02 sub di, 2
08FB: 3C 22 cmp al, '"'
08FD: 74 04 jz @f
08FF: 3C 27 cmp al, '''
0901: 75 12 jnz .end_sh_name_sec
0903: AC lodsb
0904: AB stosw
0905: AC lodsb
0906: 3C 22 cmp al, '"'
0908: 74 0B jz .end_sh_name_sec
090A: 3C 27 cmp al, '''
090C: 74 07 jz .end_sh_name_sec
090E: E2 F4 loop @b
0910: B0 7D mov al, '}'
0912: B4 0E mov ah, color_sym_yellow
0914: AB stosw
0915: 0E push cs
0916: 1F pop ds
0917: 5E pop si
0918: C3 ret
0919: 0E push cs
091A: 1F pop ds
091B: BF 1E 03 mov di, default_section_name
091E: EB BB jmp .def_sect_name
0920: 8B 7E F4 mov di, point_default
0923: 68 00 20 push ini_data_
0926: 07 pop es
0927: 89 F9 mov cx, di
0929: 89 CB mov bx, cx
092B: FD std
092C: B0 0A mov al, 0xa
092E: F2 repnz
092F: AE scasb
0930: E3 25 jcxz .go_
0932: 89 7E C6 mov find_sec_di, di
0935: 89 F9 mov cx, di
0937: 29 CB sub bx, cx
0939: 89 D9 mov cx, bx
093B: FC cld
093C: E8 34 FF call get_firs_sym
093F: E3 0D jcxz ._not_section
0941: 3B 7E F6 cmp di, point_loader
0944: 74 08 jz ._not_section
0946: 3C 5B cmp al, '['
0948: 75 04 jnz ._not_section
094A: 89 7E F4 mov point_default, di
094D: C3 ret
094E: 8B 7E C6 mov di, find_sec_di
0951: 89 F9 mov cx, di
0953: 89 CB mov bx, cx
0955: EB D4 jmp .find_start_section
0957: FC cld
0958: 89 D9 mov cx, bx
095A: 26 8A 05 mov al, byte [ es : di ]
095D: 68 6A 09 push word .f_go
0960: 3C 20 cmp al, ' '
0962: 74 03 jz @f
0964: E9 2F FF jmp get_firs_sym.not_space
0967: E9 21 FF jmp get_firs_sym.first_sp
096A: E3 E1 jcxz .exit_scan_sect
096C: 3B 7E F6 cmp di, point_loader
096F: 74 DC jz .exit_scan_sect
0971: 3C 5B cmp al, '['
0973: 75 D8 jnz .exit_scan_sect
0975: 89 7E F4 mov point_default, di
0978: C3 ret
0979: 8B 7E F4 mov di, point_default
097C: 68 00 20 push ini_data_
097F: 07 pop es
0980: 8B 4E FE mov cx, save_cx
0983: 29 F9 sub cx, di
0985: EB 17 jmp .let_s_go
0987: 68 00 20 push ini_data_
098A: 07 pop es
098B: 8B 4E FE mov cx, save_cx
098E: 26 8A 05 mov al, byte [ es : di ]
0991: 68 A1 09 push word .let_s_go_ret
0994: 3C 20 cmp al, ' '
0996: 74 03 jz @f
0998: E9 FB FE jmp get_firs_sym.not_space
099B: E9 ED FE jmp get_firs_sym.first_sp
099E: E8 D2 FE call get_firs_sym
09A1: E3 0C jcxz .exit_scan_sect
09A3: 3C 5B cmp al, '['
09A5: 75 F7 jnz .let_s_go
09A7: 3B 7E F6 cmp di, point_loader
09AA: 74 F2 jz .let_s_go
09AC: 89 7E F4 mov point_default, di
09AF: C3 ret
09B0: 8D 76 F2 lea si, point_to_hframe
09B3: BF 22 03 mov di, 962 - 160
09B6: 8B 56 F4 mov dx, point_default
09B9: B9 12 00 mov cx, 18
09BC: 8B 1C mov bx, [ si ]
09BE: 81 C7 A0 00 add di, 160
09C2: 39 D3 cmp bx, dx
09C4: 74 05 jz .clean_cursor_
09C6: 83 EE 02 sub si, 2
09C9: E2 F1 loop .clean_show_cur
09CB: 68 00 B8 push 0xb800
09CE: 07 pop es
09CF: 50 push ax
09D0: 89 76 CA mov point_to_point_def, si
09D3: 31 C0 xor ax, ax
09D5: B8 20 07 mov ax, 0x0720
09D8: AB stosw
09D9: 83 C7 44 add di, 68
09DC: AB stosw
09DD: 58 pop ax
09DE: C3 ret
09DF: B4 00 mov ah, 0
09E1: CD 1A int 1Ah
09E3: 91 xchg ax, cx
09E4: 66 C1 E0 10 shl eax, 10h
09E8: 92 xchg ax, dx
09E9: C3 ret
09EA: 1E push ds
09EB: 0E push cs
09EC: 1F pop ds
09ED: 9C pushf
09EE: FF 1E D4 1A call far dword [ old_timer ]
09F2: 66 60 pushad
09F4: E8 E8 FF call gettime
09F7: 66 2B 06 D8 1A sub eax, dword [ start_timer ]
09FC: 8B 1E D2 1A mov bx, word [ value_timeout ]
0A00: 6B DB 12 imul bx, 18
0A03: 29 C3 sub bx, ax
0A05: 76 1F jbe .timergo
0A07: 06 push es
0A08: 68 00 B8 push 0xb800
0A0B: 07 pop es
0A0C: 89 D8 mov ax, bx
0A0E: BB 12 00 mov bx, 18
0A11: 31 D2 xor dx, dx
0A13: F7 F3 div bx
0A15: BB 0A 00 mov bx, 10
0A18: BF 96 0E mov di, 3734
0A1B: E8 24 00 call .decode
0A1E: 31 C0 xor ax, ax
0A20: AB stosw
0A21: 07 pop es
0A22: 66 61 popad
0A24: 1F pop ds
0A25: CF iret
0A26: 6A 00 push 0
0A28: 07 pop es
0A29: 66 A1 D4 1A mov eax, dword [ old_timer ]
0A2D: 26 66 A3 20 00 mov [ es : 8 * 4 ], eax
0A32: 66 A3 DC 1A mov dword [ timer_ ], eax
0A36: 8B 26 E0 1A mov sp, word [ start_stack ]
0A3A: 8B 2E E2 1A mov bp, word [ save_bp_from_timer ]
0A3E: FB sti
0A3F: E9 D8 06 jmp parse_start.parse_run_only
0A42: 39 D8 cmp ax, bx
0A44: 72 09 jb @f
0A46: 31 D2 xor dx, dx
0A48: F7 F3 div bx
0A4A: 52 push dx
0A4B: E8 F4 FF call .decode
0A4E: 58 pop ax
0A4F: 0C 30 or al, 0x30
0A51: 50 push ax
0A52: B4 09 mov ah, 9
0A54: AB stosw
0A55: 58 pop ax
0A56: C3 ret
0A57: 8B 5E C8 mov bx, point_to_eframe
0A5A: 8D 76 F2 lea si, point_to_hframe
0A5D: BA C6 03 mov dx, 966
0A60: 39 DE cmp si, bx
0A62: 72 12 jb ._show_space_fb
0A64: 8B 3C mov di, [ si ]
0A66: 83 EE 02 sub si, 2
0A69: 8B 0C mov cx, [ si ]
0A6B: 29 F9 sub cx, di
0A6D: E8 2B FE call show_name_section
0A70: 81 C2 A0 00 add dx, 160
0A74: EB EA jmp .home_show_fb
0A76: 83 EA 04 sub dx, 4
0A79: 68 00 B8 push 0xb800
0A7C: 07 pop es
0A7D: 81 FA 64 0E cmp dx, 0xE64
0A81: 77 12 ja .exit_show_fb
0A83: 89 D7 mov di, dx
0A85: 31 C0 xor ax, ax
0A87: B8 20 07 mov ax, 0x0720
0A8A: B9 27 00 mov cx, 39
0A8D: F3 rep
0A8E: AB stosw
0A8F: 81 C2 A0 00 add dx, 160
0A93: EB E8 jmp @b
0A95: C3 ret
0A96: 89 C7 mov di, ax
0A98: 89 D9 mov cx, bx
0A9A: FF 66 FC jmp ret_on_ch
0A9D: C9 leave
0A9E: BE 1A 01 mov si, not_found_def_sect
0AA1: E9 F4 00 jmp err_show_ini
0AA4: C9 leave
0AA5: BE FE 00 mov si, not_found_sec_loader
0AA8: E9 ED 00 jmp err_show_ini
0AAB: C9 leave
0AAC: BE 47 01 mov si, default_eq_loader
0AAF: E9 E6 00 jmp err_show_ini
0AB2: C9 leave
0AB3: BE C4 02 mov si, point_to_default_sec_not_found
0AB6: E9 DF 00 jmp err_show_ini
0AB9: C9 leave
0ABA: BE F7 02 mov si, incorect_section_define
0ABD: E9 D8 00 jmp err_show_ini
0AC0: 68 00 B8 push word 0xb800
0AC3: 07 pop es
0AC4: C3 ret
0AC5: 00 00 00 20 file_data dw 0x0, ini_data_
0AC9: 10 00 size_data dw 16
0ACB: 6B 6F 72 64 2F 73 74 61 72 74 6F 73 2E name_ini_f db 'kord/startos.ini', 0
0AD8: 69 6E 69 00
0ADC: 00 00 00 00 loader_callback dd ?
0AE0: 00 00 load_drive dw ?
0AE2: 00 00 load_ft dw ?
0AE4: 2E 89 36 DC 0A mov word [ cs : loader_callback ], si
0AE9: 2E 8C 1E DE 0A mov word [ cs : loader_callback + 2 ], ds
0AEE: 2E A3 E0 0A mov word [ cs : load_drive ], ax
0AF2: 2E 89 1E E2 0A mov word [ cs : load_ft ], bx
0AF7: 8C C8 mov ax, cs
0AF9: 8E D0 mov ss, ax
0AFB: 31 E4 xor sp, sp
0AFD: 8E D8 mov ds, ax
0AFF: 8E C0 mov es, ax
0B01: FC cld
0B02: FB sti
0B03: B8 03 00 mov ax, 3
0B06: CD 10 int 0x10
0B08: BE 03 00 mov si, version
0B0B: E8 36 FD call printplain
0B0E: B0 23 mov al, '#'
0B10: B9 50 00 mov cx, 80
0B13: E8 27 FD call putchar
0B16: E2 FB loop @b
0B18: BE C8 03 mov si, stack_msg
0B1B: E8 26 FD call printplain
0B1E: 31 DB xor bx, bx
0B20: 8E DB mov ds, bx
0B22: FF 77 1A push word [ bx + 6 * 4 + 2 ]
0B25: FF 77 18 push word [ bx + 6 * 4 ]
0B28: C7 47 18 4A 0B mov word [ bx + 6 * 4 ], ud16
0B2D: 8C 4F 1A mov word [ bx + 6 * 4 + 2 ], cs
0B30: 66 31 C0 xor eax, eax
0B33: 0F A2 cpuid
0B35: 66 85 C0 test eax, eax
0B38: 74 10 jz cpubad
0B3A: 66 31 C0 xor eax, eax
0B3D: 40 inc ax
0B3E: 0F A2 cpuid
0B40: F6 C2 10 test dl, 10h
0B43: 74 05 jz cpubad
0B45: F6 C2 20 test dl, 20h
0B48: 75 12 jnz cpugood
0B4A: 8F 06 18 00 pop word [ 6 * 4 ]
0B4E: 8F 06 1A 00 pop word [ 6 * 4 + 2 ]
0B52: 0E push cs
0B53: 1F pop ds
0B54: BE 4C 00 mov si, badprocessor
0B57: E8 EA FC call printplain
0B5A: EB FE jmp $
0B5C: 66 8F 06 18 00 pop dword [ 6 * 4 ]
0B61: 0E push cs
0B62: 1F pop ds
0B63: 66 0F B7 E4 movzx esp, sp
0B67: B9 03 00 mov cx, loop_read_startos_file
0B6C: 31 C0 xor ax, ax
0B6E: BF C5 0A mov di, file_data
0B71: 40 inc ax
0B72: 51 push cx
0B73: FF 1E DC 0A call far dword [ loader_callback ]
0B77: 59 pop cx
0B78: 0E push cs
0B79: 0E push cs
0B7A: 1F pop ds
0B7B: 07 pop es
0B7C: 85 DB test bx, bx
0B7E: 74 28 jz check_conf_file
0B80: 49 dec cx
0B81: 75 E9 jnz load_startos_file
0B83: BE 68 00 mov si, error_ini_f1
0B86: 4B dec bx
0B87: 74 0F jz err_show_ini
0B89: BE 95 00 mov si, error_ini_f2
0B8C: 4B dec bx
0B8D: 74 09 jz err_show_ini
0B8F: BE B0 00 mov si, error_ini_f3
0B92: 4B dec bx
0B93: 74 03 jz err_show_ini
0B95: BE CD 00 mov si, error_ini_nf
0B98: E8 A9 FC call printplain
0B9B: BE 26 02 mov si, error_ini_common
0B9E: E8 A3 FC call printplain
0BA1: 31 C0 xor ax, ax
0BA3: CD 16 int 16h
0BA5: EB FE jmp $
0BA8: 50 push ax
0BA9: B9 0A 00 mov cx, 0x0a
0BAC: BF 00 04 mov di, show_decode
0BAF: E8 73 FC call decode
0BB2: BE EF 03 mov si, show_string
0BB5: E8 8C FC call printplain
0BB8: BE 90 02 mov si, load_ini
0BBB: E8 86 FC call printplain
0BBE: 59 pop cx
0BBF: C8 00 01 00 enter 256, 0
0BC3: 89 2E E2 1A mov word [ save_bp_from_timer ], bp
0BC7: 89 4E FE mov save_cx, cx
0BCA: C4 3E C5 0A les di, dword [ file_data ]
0BCE: 31 C0 xor ax, ax
0BD0: 89 46 F8 mov status_flag, ax
0BD3: C7 46 C4 00 30 mov info_real_mode_size, ini_data_ + 0x1000
0BD8: FC cld
0BD9: C7 46 FC EE 0B mov ret_on_ch, .start
0BDE: 26 8A 05 mov al, byte [ es : di ]
0BE1: 68 F1 0B push word .first_ret
0BE4: 3C 20 cmp al, ' '
0BE6: 74 03 jz .first_sp_1
0BE8: E9 AB FC jmp get_firs_sym.not_space
0BEB: E9 9D FC jmp get_firs_sym.first_sp
0BEE: E8 82 FC call get_firs_sym
0BF1: 85 C9 test cx, cx
0BF3: 0F 84 AD FE jz error.not_loader
0BF7: 3C 5B cmp al, '['
0BF9: 74 02 jz .parse_loader
0BFB: EB F1 jmp .start
0BFD: 89 CB mov bx, cx
0BFF: 89 F8 mov ax, di
0C01: BE AC 07 mov si, parse_loader
0C04: B9 08 00 mov cx, parse_loader_e - parse_loader
0C07: F3 repe
0C08: A6 cmpsb
0C09: 0F 85 89 FE jnz error.rest_value
0C0D: 89 46 F6 mov point_loader, ax
0C10: 83 EB 08 sub bx, parse_loader_e - parse_loader
0C13: 01 CB add bx, cx
0C15: 89 D9 mov cx, bx
0C17: 60 pusha
0C18: BE 35 04 mov si, lm_l_found
0C1B: E8 26 FC call printplain
0C1E: 61 popa
0C1F: 89 FA mov dx, di
0C21: E8 4F FC call get_firs_sym
0C24: E3 04 jcxz .loader_f_end
0C26: 3C 5B cmp al, '['
0C28: 75 F7 jnz @b
0C2A: 29 CB sub bx, cx
0C2C: 89 D7 mov di, dx
0C2E: 89 D9 mov cx, bx
0C30: C7 46 FC 35 0C mov ret_on_ch, .get_next_str
0C35: E8 3B FC call get_firs_sym
0C38: 85 C9 test cx, cx
0C3A: 0F 84 57 01 jz .end_loader
0C3E: 3C 74 cmp al, 't'
0C40: 0F 84 DE 00 jz .loader_timeout
0C44: 3C 64 cmp al, 'd'
0C46: 75 ED jnz .get_next_str
0C48: 89 CB mov bx, cx
0C4A: 89 F8 mov ax, di
0C4C: BE BB 07 mov si, parse_l_default
0C4F: B9 07 00 mov cx, parse_l_default_e - parse_l_default
0C52: F3 repe
0C53: A6 cmpsb
0C54: 0F 85 3E FE jnz error.rest_value
0C58: 83 EB 07 sub bx, parse_l_default_e - parse_l_default
0C5B: 01 CB add bx, cx
0C5D: 89 D9 mov cx, bx
0C5F: F7 46 F8 01 00 test status_flag, flag_found_default
0C64: 74 08 jz .correct_is_not_set
0C66: BE 7A 01 mov si, found_equal_default
0C69: E8 D8 FB call printplain
0C6C: EB C7 jmp .get_next_str
0C6E: B8 20 3D mov ax, 0x3d20
0C71: F3 repe
0C72: AE scasb
0C73: 85 C9 test cx, cx
0C75: 0F 84 1C 01 jz .end_loader
0C79: 26 3A 65 FF cmp ah, byte [ es : di - 1 ]
0C7D: 75 B6 jnz .get_next_str
0C7F: F3 repe
0C80: AE scasb
0C81: 41 inc cx
0C82: 4F dec di
0C83: 89 CB mov bx, cx
0C85: 89 FA mov dx, di
0C87: 26 8A 05 mov al, byte [ es : di ]
0C8A: 47 inc di
0C8B: 49 dec cx
0C8C: 85 C9 test cx, cx
0C8E: 0F 84 0B FE jz error.error_get_size_d_sect
0C92: 3C 20 cmp al, ' '
0C94: 74 F1 jz @b
0C96: 3C 0D cmp al, 0xd
0C98: 74 04 jz .found_size_d_sect
0C9A: 3C 0A cmp al, 0xa
0C9C: 75 E9 jnz @b
0C9E: 41 inc cx
0C9F: 89 D8 mov ax, bx
0CA1: 29 CB sub bx, cx
0CA3: 89 5E FA mov save_cx_d, bx
0CA6: 89 D7 mov di, dx
0CA8: 89 D9 mov cx, bx
0CAA: 89 C3 mov bx, ax
0CAC: 89 D0 mov ax, dx
0CAE: BE AC 07 mov si, parse_loader
0CB1: 46 inc si
0CB2: F3 repe
0CB3: A6 cmpsb
0CB4: 75 03 jnz .check_section
0CB6: E9 F2 FD jmp error.default_eq_loader
0CB9: 89 D9 mov cx, bx
0CBB: 89 C7 mov di, ax
0CBD: 89 FE mov si, di
0CBF: 57 push di
0CC0: 51 push cx
0CC1: 8B 4E FE mov cx, save_cx
0CC4: C4 3E C5 0A les di, dword [ file_data ]
0CC8: 26 8A 05 mov al, byte [ es : di ]
0CCB: 68 DB 0C push word .first_ret_d
0CCE: 3C 20 cmp al, ' '
0CD0: 74 03 jz .first_sp_1_d
0CD2: E9 C1 FB jmp get_firs_sym.not_space
0CD5: E9 B3 FB jmp get_firs_sym.first_sp
0CD8: E8 98 FB call get_firs_sym
0CDB: E3 38 jcxz .correct_exit
0CDD: 3C 5B cmp al, '['
0CDF: 74 02 jz .found_sect_d
0CE1: EB F5 jmp .start_d
0CE3: 89 CB mov bx, cx
0CE5: 89 F8 mov ax, di
0CE7: 56 push si
0CE8: 8B 4E FA mov cx, save_cx_d
0CEB: 06 push es
0CEC: 1F pop ds
0CED: 47 inc di
0CEE: F3 repe
0CEF: A6 cmpsb
0CF0: 0E push cs
0CF1: 1F pop ds
0CF2: 5E pop si
0CF3: 75 1A jnz .not_compare_d_s
0CF5: 26 80 3D 5D cmp byte [ es : di ], ']'
0CF9: 75 14 jnz .not_compare_d_s
0CFB: 83 4E F8 01 or status_flag, flag_found_default
0CFF: 59 pop cx
0D00: 5F pop di
0D01: 89 46 F4 mov point_default, ax
0D04: 60 pusha
0D05: BE 96 04 mov si, lm_lf_default_f
0D08: E8 39 FB call printplain
0D0B: 61 popa
0D0C: E9 26 FF jmp .get_next_str
0D0F: 89 D9 mov cx, bx
0D11: 89 C7 mov di, ax
0D13: EB C3 jmp .start_d
0D15: 59 pop cx
0D16: 5F pop di
0D17: 60 pusha
0D18: BE 58 04 mov si, lm_lf_default
0D1B: E8 26 FB call printplain
0D1E: 61 popa
0D1F: E9 13 FF jmp .get_next_str
0D22: 89 CB mov bx, cx
0D24: 89 F8 mov ax, di
0D26: BE B4 07 mov si, parse_l_timeout
0D29: B9 07 00 mov cx, parse_l_timeout_e - parse_l_timeout
0D2C: F3 repe
0D2D: A6 cmpsb
0D2E: 0F 85 64 FD jnz error.rest_value
0D32: 83 EB 07 sub bx, parse_l_timeout_e - parse_l_timeout
0D35: 01 CB add bx, cx
0D37: 89 D9 mov cx, bx
0D39: F7 46 F8 02 00 test status_flag, flag_found_timeout
0D3E: 74 09 jz .correct_is_not_set_t
0D40: BE B0 01 mov si, found_equal_timeout
0D43: E8 FE FA call printplain
0D46: E9 EC FE jmp .get_next_str
0D49: B8 20 3D mov ax, 0x3d20
0D4C: F3 repe
0D4D: AE scasb
0D4E: E3 35 jcxz .timeout_sec_end_d
0D50: 26 3A 65 FF cmp ah, byte [ es : di - 1 ]
0D54: 0F 85 DD FE jnz .get_next_str
0D58: F3 repe
0D59: AE scasb
0D5A: 41 inc cx
0D5B: 4F dec di
0D5C: 51 push cx
0D5D: 31 DB xor bx, bx
0D5F: B9 02 00 mov cx, 2
0D62: 26 8A 05 mov al, byte [ es : di ]
0D65: 3C 30 cmp al, '0'
0D67: 72 0B jb .end_get_val_t
0D69: 3C 39 cmp al, '9'
0D6B: 77 07 ja .end_get_val_t
0D6D: 6B DB 0A imul bx, 10
0D70: 34 30 xor al, 0x30
0D72: 00 C3 add bl, al
0D74: 47 inc di
0D75: E2 EB loop @b
0D77: 89 1E D2 1A mov word [ value_timeout ], bx
0D7B: 60 pusha
0D7C: BE 47 04 mov si, lm_lf_timeout
0D7F: E8 C2 FA call printplain
0D82: 61 popa
0D83: EB 0C jmp @f
0D85: C7 06 D2 1A 05 00 mov word [ value_timeout ], default_timeout_value
0D8B: BE E6 01 mov si, set_default_timeout_val
0D8E: E8 B3 FA call printplain
0D91: 59 pop cx
0D92: E9 A0 FE jmp .get_next_str
0D95: 60 pusha
0D96: BE AD 04 mov si, lm_l_end
0D99: E8 A8 FA call printplain
0D9C: 61 popa
0D9D: 31 C0 xor ax, ax
0D9F: CD 16 int 16h
0DA1: 60 pusha
0DA2: A1 D2 1A mov ax, word [ value_timeout ]
0DA5: B9 0A 00 mov cx, 0x0a
0DA8: BF 07 04 mov di, show_db1
0DAB: 66 C7 05 20 20 20 20 mov dword [ ds : di ], ' '
0DB2: C7 45 04 20 20 mov word [ ds : di + 4 ], ' '
0DB7: E8 6B FA call decode
0DBA: BE 07 04 mov si, show_db1
0DBD: E8 84 FA call printplain
0DC0: 61 popa
0DC1: 85 C0 test ax, ax
0DC3: 0F 84 53 03 jz .parse_run_only
0DC7: 60 pusha
0DC8: BE C5 04 mov si, show_all_sect
0DCB: E8 76 FA call printplain
0DCE: 61 popa
0DCF: B0 F6 mov al, 0xf6
0DD1: E6 60 out 0x60, al
0DD3: 31 C9 xor cx, cx
0DD5: E4 64 in al, 64h
0DD7: 24 02 and al, 00000010b
0DD9: E0 FA loopnz .wait_loop
0DDB: B0 F3 mov al, 0xf3
0DDD: E6 60 out 0x60, al
0DDF: 31 C9 xor cx, cx
0DE1: E4 64 in al, 64h
0DE3: A8 02 test al, 2
0DE5: E0 FA loopnz @b
0DE7: B0 00 mov al, 0
0DE9: E6 60 out 0x60, al
0DEB: 31 C9 xor cx, cx
0DED: E4 64 in al, 64h
0DEF: A8 02 test al, 2
0DF1: E0 FA loopnz @b
0DF3: E8 E9 FB call gettime
0DF6: 66 A3 D8 1A mov dword [ start_timer ], eax
0DFA: C7 06 DC 1A EA 09 mov word [ timer_ ], newtimer
0E00: 8C 0E DE 1A mov word [ timer_ + 2 ], cs
0E04: FA cli
0E05: 6A 00 push 0
0E07: 07 pop es
0E08: 26 66 FF 36 20 00 push dword [ es : 8 * 4 ]
0E0E: 66 8F 06 D4 1A pop dword [ old_timer ]
0E13: 66 FF 36 DC 1A push dword [ timer_ ]
0E18: 26 66 8F 06 20 00 pop dword [ es : 8 * 4 ]
0E1E: FB sti
0E1F: C7 46 BE 12 00 mov save_descript_size, 18
0E24: 31 C0 xor ax, ax
0E26: B8 20 07 mov ax, 0x0720
0E29: 68 00 B8 push 0xb800
0E2C: 07 pop es
0E2D: 31 FF xor di, di
0E2F: B9 D0 07 mov cx, 25 * 80
0E32: F3 rep
0E33: AB stosw
0E34: BF A4 00 mov di, 164
0E37: BE 03 00 mov si, version
0E3A: B9 19 00 mov cx, version_end - version
0E3D: B4 0E mov ah, color_sym_yellow
0E3F: AC lodsb
0E40: AB stosw
0E41: E2 FC loop @b
0E43: BF 1E 01 mov di, 286
0E46: B4 0C mov ah, color_sym_pink
0E48: B0 4B mov al, 'K'
0E4A: AB stosw
0E4B: B0 20 mov al, ' '
0E4D: AB stosw
0E4E: B4 07 mov ah, color_sym_lightgray
0E50: BE 3F 00 mov si, soft_mes
0E53: B9 0D 00 mov cx, soft_mes_end - soft_mes
0E56: AC lodsb
0E57: AB stosw
0E58: E2 FC loop @b
0E5A: BF E0 01 mov di, 480
0E5D: B4 0E mov ah, color_sym_yellow
0E5F: B0 C4 mov al, 0xC4
0E61: B9 3D 00 mov cx, 61
0E64: F3 rep
0E65: AB stosw
0E66: BF 24 03 mov di, 804
0E69: BE 1C 00 mov si, select_section
0E6C: B9 0F 00 mov cx, select_section_end - select_section
0E6F: B4 07 mov ah, color_sym_lightgray
0E71: AC lodsb
0E72: AB stosw
0E73: E2 FC loop @b
0E75: BF 70 03 mov di, 880
0E78: BE 2B 00 mov si, section_description
0E7B: B9 14 00 mov cx, section_description_end - section_description
0E7E: AC lodsb
0E7F: AB stosw
0E80: E2 FC loop @b
0E82: 8B 4E FE mov cx, save_cx
0E85: C4 3E C5 0A les di, dword [ file_data ]
0E89: 89 FE mov si, di
0E8B: 89 CB mov bx, cx
0E8D: BA 12 00 mov dx, size_show_section
0E90: 26 8A 05 mov al, byte [ es : di ]
0E93: 68 B9 0E push word .first_ret_bl_sc
0E96: 3C 20 cmp al, ' '
0E98: 74 03 jz .first_bl_sc
0E9A: E9 F9 F9 jmp get_firs_sym.not_space
0E9D: E9 EB F9 jmp get_firs_sym.first_sp
0EA0: E8 D0 F9 call get_firs_sym
0EA3: 85 C9 test cx, cx
0EA5: 0F 84 09 FC jz error.correct_exit_bl
0EA9: 3C 5B cmp al, '['
0EAB: 75 F3 jnz .start_hbl
0EAD: 89 FE mov si, di
0EAF: 89 CB mov bx, cx
0EB1: BA 12 00 mov dx, size_show_section
0EB4: EB 09 jmp .analisist_al
0EB6: E8 BA F9 call get_firs_sym
0EB9: 85 C9 test cx, cx
0EBB: 0F 84 F3 FB jz error.correct_exit_bl
0EBF: 3C 5B cmp al, '['
0EC1: 75 F3 jnz .start_bl
0EC3: 3B 7E F6 cmp di, point_loader
0EC6: 74 EE jz .start_bl
0EC8: 3B 7E F4 cmp di, point_default
0ECB: 74 05 jz .save_point_def
0ECD: 4A dec dx
0ECE: 75 E6 jnz .start_bl
0ED0: EB CE jmp .start_hbl
0ED2: 89 F7 mov di, si
0ED4: 89 D9 mov cx, bx
0ED6: 8D 76 F2 lea si, point_to_hframe
0ED9: BA 13 00 mov dx, size_show_section + 1
0EDC: 26 8A 05 mov al, byte [ es : di ]
0EDF: 68 EF 0E push word .first_ret_mfb
0EE2: 3C 20 cmp al, ' '
0EE4: 74 03 jz .first_bl_mbf
0EE6: E9 AD F9 jmp get_firs_sym.not_space
0EE9: E9 9F F9 jmp get_firs_sym.first_sp
0EEC: E8 84 F9 call get_firs_sym
0EEF: E3 13 jcxz .val_buff_comp
0EF1: 3C 5B cmp al, '['
0EF3: 75 F7 jnz .start_mfb
0EF5: 3B 7E F6 cmp di, point_loader
0EF8: 74 F2 jz .start_mfb
0EFA: 89 3C mov [ si ], di
0EFC: 83 EE 02 sub si, 2
0EFF: 4A dec dx
0F00: 75 EA jnz .start_mfb
0F02: EB 08 jmp @f
0F04: FF 76 FE push save_cx
0F07: 8F 04 pop word [ si ]
0F09: 83 EE 02 sub si, 2
0F0C: 83 C6 04 add si, 4
0F0F: 89 76 C8 mov point_to_eframe, si
0F12: E8 42 FB call show_bl_sc_sect
0F15: 8D 76 F2 lea si, point_to_hframe
0F18: BF 22 03 mov di, 962 - 160
0F1B: 8B 46 F4 mov ax, point_default
0F1E: B9 12 00 mov cx, size_show_section
0F21: 8B 1C mov bx, [ si ]
0F23: 81 C7 A0 00 add di, 160
0F27: 39 C3 cmp bx, ax
0F29: 74 05 jz .show_cursor_activ
0F2B: 83 EE 02 sub si, 2
0F2E: E2 F1 loop .home_show_cur
0F30: 89 76 CA mov point_to_point_def, si
0F33: B8 10 04 mov ax, ( color_sym_red * 0x100 + 0x10 )
0F36: AB stosw
0F37: 83 C7 44 add di, 68
0F3A: 40 inc ax
0F3B: AB stosw
0F3C: 8B 7E F4 mov di, point_default
0F3F: 68 00 20 push ini_data_
0F42: 8B 76 CA mov si, point_to_point_def
0F45: 07 pop es
0F46: 83 EE 02 sub si, 2
0F49: 8B 0C mov cx, [ si ]
0F4B: 29 F9 sub cx, di
0F4D: E8 23 F9 call get_firs_sym
0F50: 85 C9 test cx, cx
0F52: 0F 84 91 00 jz .exit?0Pz
0F56: 3C 64 cmp al, 'd'
0F58: 75 F3 jnz .start_p_sh_d?0Py
0F5A: 89 CB mov bx, cx
0F5C: 89 F8 mov ax, di
0F5E: BE C5 07 mov si, parse_descript
0F61: B9 08 00 mov cx, parse_descript_e - parse_descript
0F64: F3 repe
0F65: A6 cmpsb
0F66: 75 78 jnz .rest_value_loop_sh_d?0Q0
0F68: 83 EB 08 sub bx, parse_descript_e - parse_descript
0F6B: 01 CB add bx, cx
0F6D: 89 D9 mov cx, bx
0F6F: B8 20 3D mov ax, 0x3d20
0F72: F3 repe
0F73: AE scasb
0F74: E3 6A jcxz .rest_value_loop_sh_d?0Q0
0F76: 26 3A 65 FF cmp ah, byte [ es : di - 1 ]
0F7A: 75 64 jnz .rest_value_loop_sh_d?0Q0
0F7C: F3 repe
0F7D: AE scasb
0F7E: 41 inc cx
0F7F: 4F dec di
0F80: 57 push di
0F81: 5E pop si
0F82: 06 push es
0F83: 1F pop ds
0F84: 68 00 B8 push 0xb800
0F87: 07 pop es
0F88: BF 10 04 mov di, 1040
0F8B: BB 12 00 mov bx, 18
0F8E: 89 7E C6 mov find_sec_di, di
0F91: 89 5E FA mov save_cx_d, bx
0F94: 57 push di
0F95: 31 C0 xor ax, ax
0F97: B9 26 00 mov cx, 38
0F9A: 57 push di
0F9B: F3 rep
0F9C: AB stosw
0F9D: 5F pop di
0F9E: 39 5E BE cmp save_descript_size, bx
0FA1: 74 07 jz @f
0FA3: 81 C7 A0 00 add di, 160
0FA7: 4B dec bx
0FA8: 75 ED jnz @b
0FAA: 5F pop di
0FAB: AC lodsb
0FAC: B4 0A mov ah, color_sym_lettuce
0FAE: 3C 22 cmp al, '"'
0FB0: 74 04 jz .loop_message?0Q2
0FB2: 3C 27 cmp al, '''
0FB4: 75 20 jnz .end_sh_desc_sec?0Q1
0FB6: B9 26 00 mov cx, 38
0FB9: AC lodsb
0FBA: 3C 22 cmp al, '"'
0FBC: 74 18 jz .end_sh_desc_sec?0Q1
0FBE: 3C 27 cmp al, '''
0FC0: 74 14 jz .end_sh_desc_sec?0Q1
0FC2: AB stosw
0FC3: E2 F4 loop @b
0FC5: 81 46 C6 A0 00 add find_sec_di, 160
0FCA: 8B 7E C6 mov di, find_sec_di
0FCD: FF 4E FA dec save_cx_d
0FD0: 83 7E FA 00 cmp save_cx_d, 0
0FD4: 75 E0 jnz .loop_message?0Q2
0FD6: FF 76 FA push save_cx_d
0FD9: 8F 46 BE pop save_descript_size
0FDC: 0E push cs
0FDD: 1F pop ds
0FDE: EB 07 jmp .exit?0Pz
0FE0: 89 C7 mov di, ax
0FE2: 89 D9 mov cx, bx
0FE4: E9 66 FF jmp .start_p_sh_d?0Py
0FE7: 66 A1 D4 1A mov eax, dword [ old_timer ]
0FEB: 66 3B 06 DC 1A cmp eax, dword [ timer_ ]
0FF0: 74 5E jz .interrupt_16
0FF2: 31 C0 xor ax, ax
0FF4: BF 20 0D mov di, 3360
0FF7: B9 40 01 mov cx, 80 * 4
0FFA: F3 rep
0FFB: AB stosw
0FFC: BF 22 0D mov di, 3362
0FFF: B4 0C mov ah, color_sym_pink
1001: B0 DA mov al, 0xDA
1003: AB stosw
1004: B0 C4 mov al, 0xc4
1006: B9 4C 00 mov cx, 76
1009: F3 rep
100A: AB stosw
100B: B0 BF mov al, 0xBF
100D: AB stosw
100E: 83 C7 04 add di, 4
1011: B0 B3 mov al, 0xb3
1013: AB stosw
1014: 81 C7 98 00 add di, 152
1018: AB stosw
1019: 83 C7 04 add di, 4
101C: AB stosw
101D: 81 C7 98 00 add di, 152
1021: AB stosw
1022: 83 C7 04 add di, 4
1025: B0 C0 mov al, 0xc0
1027: AB stosw
1028: B0 C4 mov al, 0xc4
102A: B9 4C 00 mov cx, 76
102D: F3 rep
102E: AB stosw
102F: B0 D9 mov al, 0xd9
1031: AB stosw
1032: BE 2E 03 mov si, start_msg
1035: B9 4A 00 mov cx, start_msg_e - start_msg
1038: BF C6 0D mov di, 3526
103B: AC lodsb
103C: AB stosw
103D: E2 FC loop @b
103F: 83 C7 2C add di, 44
1042: BE 78 03 mov si, time_msg
1045: B9 2D 00 mov cx, time_msg_e - time_msg
1048: AC lodsb
1049: AB stosw
104A: E2 FC loop @b
104C: 89 26 E0 1A mov word [ start_stack ], sp
1050: 31 C0 xor ax, ax
1052: CD 16 int 0x16
1054: 66 8B 1E D4 1A mov ebx, dword [ old_timer ]
1059: 66 3B 1E DC 1A cmp ebx, dword [ timer_ ]
105E: 74 2A jz @f
1060: FA cli
1061: 6A 00 push 0
1063: 07 pop es
1064: 26 66 89 1E 20 00 mov [ es : 8 * 4 ], ebx
106A: 66 89 1E DC 1A mov dword [ timer_ ], ebx
106F: FB sti
1070: 50 push ax
1071: 68 00 B8 push 0xb800
1074: 07 pop es
1075: 31 C0 xor ax, ax
1077: B8 20 07 mov ax, 0x0720
107A: BF 20 0D mov di, 3360
107D: B9 40 01 mov cx, 80 * 4
1080: F3 rep
1081: AB stosw
1082: 68 00 20 push ini_data_
1085: 07 pop es
1086: E8 CE F9 call show_bl_sc_sect
1089: 58 pop ax
108A: E8 23 F9 call clean_active_cursor
108D: 80 FC 48 cmp ah, 0x48
1090: 74 21 jz .up
1092: 80 FC 50 cmp ah, 0x50
1095: 74 3A jz .down
1097: 80 FC 49 cmp ah, 0x49
109A: 74 53 jz .pgup
109C: 80 FC 51 cmp ah, 0x51
109F: 74 5B jz .pgdown
10A1: 80 FC 47 cmp ah, 0x47
10A4: 74 63 jz .home
10A6: 80 FC 4F cmp ah, 0x4f
10A9: 74 66 jz .end
10AB: 3C 0D cmp al, 0xD
10AD: 0F 85 64 FE jnz .show_active_cursor
10B1: EB 6F jmp .end_show_all
10B3: 8B 76 CA mov si, point_to_point_def
10B6: 83 C6 02 add si, 2
10B9: 8D 46 F2 lea ax, point_to_hframe
10BC: 39 C6 cmp si, ax
10BE: 77 0B ja @f
10C0: 89 76 CA mov point_to_point_def, si
10C3: 8B 04 mov ax, [ si ]
10C5: 89 46 F4 mov point_default, ax
10C8: E9 4A FE jmp .show_active_cursor
10CB: E8 52 F8 call find_before_sect
10CE: E9 B1 FD jmp .show_all_scr
10D1: 8B 76 CA mov si, point_to_point_def
10D4: 8B 46 C8 mov ax, point_to_eframe
10D7: 83 EE 02 sub si, 2
10DA: 39 C6 cmp si, ax
10DC: 72 0B jb @f
10DE: 89 76 CA mov point_to_point_def, si
10E1: 8B 04 mov ax, [ si ]
10E3: 89 46 F4 mov point_default, ax
10E6: E9 2C FE jmp .show_active_cursor
10E9: E8 8D F8 call find_next_sect
10EC: E9 93 FD jmp .show_all_scr
10EF: B9 12 00 mov cx, size_show_section
10F2: 51 push cx
10F3: E8 2A F8 call find_before_sect
10F6: 59 pop cx
10F7: E2 F9 loop @b
10F9: E9 86 FD jmp .show_all_scr
10FC: B9 12 00 mov cx, size_show_section
10FF: 51 push cx
1100: E8 76 F8 call find_next_sect
1103: 59 pop cx
1104: E2 F9 loop @b
1106: E9 79 FD jmp .show_all_scr
1109: 31 FF xor di, di
110B: E8 79 F8 call find_next_sect.h
110E: E9 71 FD jmp .show_all_scr
1111: 8B 7E FE mov di, save_cx
1114: E8 0C F8 call find_before_sect.e
1117: E9 68 FD jmp .show_all_scr
111A: 60 pusha
111B: BE D7 04 mov si, no_show_only_w
111E: E8 23 F7 call printplain
1121: 61 popa
1122: 8B 7E F4 mov di, point_default
1125: 68 00 20 push ini_data_
1128: 07 pop es
1129: 8B 76 CA mov si, point_to_point_def
112C: 83 EE 02 sub si, 2
112F: 8B 0C mov cx, [ si ]
1131: 31 C0 xor ax, ax
1133: 29 F9 sub cx, di
1135: 89 4E FA mov save_cx_d, cx
1138: 89 46 F8 mov status_flag, ax
113B: BE 2B 05 mov si, ramdiskFS_st
113E: E8 03 F7 call printplain
1141: 31 C0 xor ax, ax
1143: 89 46 C0 mov show_errors_sect, ax
1146: B4 88 mov ah, 0x88
1148: CD 15 int 0x15
114A: 73 02 jnc ._support_function_use_free_memory
114C: 31 C0 xor ax, ax
114E: 89 46 C2 mov free_ad_memory, ax
1151: 60 pusha
1152: 66 0F B7 C0 movzx eax, ax
1156: B9 0A 00 mov cx, 0x0a
1159: BF 46 05 mov di, free_memory_msg
115C: 66 C7 05 20 20 20 20 mov dword [ ds : di ], ' '
1163: C7 45 04 20 20 mov word [ ds : di + 4 ], ' '
1168: E8 BA F6 call decode
116B: BE 46 05 mov si, free_memory_msg
116E: E8 D3 F6 call printplain
1171: 61 popa
1172: 8B 7E F4 mov di, point_default
1175: 8B 4E FA mov cx, save_cx_d
1178: E8 F8 F6 call get_firs_sym
117B: 85 C9 test cx, cx
117D: 74 6E jz ._end_parse_RS?0k2
117F: 3C 52 cmp al, 'R'
1181: 75 F5 jnz .start_p_RS?0ju
1183: 89 CB mov bx, cx
1185: 89 F8 mov ax, di
1187: BE D9 07 mov si, parse_RamdiskSize
118A: B9 0B 00 mov cx, parse_RamdiskSize_e - parse_RamdiskSize
118D: F3 repe
118E: A6 cmpsb
118F: 75 4C jnz .rest_value_loop_RS?0jz
1191: 83 EB 0B sub bx, parse_RamdiskSize_e - parse_RamdiskSize
1194: 01 CB add bx, cx
1196: 89 D9 mov cx, bx
1198: F7 46 F8 02 00 test status_flag, flag_found_RS
119D: 74 00 jz .correct_is_not_set_RS?0jv
119F: B8 20 3D mov ax, 0x3d20
11A2: F3 repe
11A3: AE scasb
11A4: E3 3D jcxz .end_get_RS_ERROR_1?0k0
11A6: 26 3A 65 FF cmp ah, byte [ es : di - 1 ]
11AA: 75 CC jnz .start_p_RS?0ju
11AC: F3 repe
11AD: AE scasb
11AE: 41 inc cx
11AF: 4F dec di
11B0: 31 DB xor bx, bx
11B2: B9 05 00 mov cx, 5
11B5: 26 8A 05 mov al, byte [ es : di ]
11B8: 3C 30 cmp al, '0'
11BA: 72 04 jb .CS?0jw
11BC: 3C 39 cmp al, '9'
11BE: 76 06 jbe .correct_val_RS?0jx
11C0: 3C 4B cmp al, 'K'
11C2: 74 0C jz .correct_size_RS?0jy
11C4: EB 23 jmp .end_get_RS_ERROR_2?0k1
11C6: 6B DB 0A imul bx, 10
11C9: 34 30 xor al, 0x30
11CB: 00 C3 add bl, al
11CD: 47 inc di
11CE: E2 E5 loop @b
11D0: 85 DB test bx, bx
11D2: 75 07 jnz @f
11D4: 83 4E C0 04 or show_errors_sect, show_error_3
11D8: BB 40 00 mov bx, 64
11DB: EB 10 jmp ._end_parse_RS?0k2
11DD: 89 C7 mov di, ax
11DF: 89 D9 mov cx, bx
11E1: EB 95 jmp .start_p_RS?0ju
11E3: 83 4E C0 01 or show_errors_sect, show_error_1
11E7: EB 04 jmp ._end_parse_RS?0k2
11E9: 83 4E C0 02 or show_errors_sect, show_error_2
11ED: 60 pusha
11EE: 66 0F B7 C3 movzx eax, bx
11F2: B9 0A 00 mov cx, 0x0a
11F5: BF 71 05 mov di, RamdiskSize_msg
11F8: 66 C7 05 20 20 20 20 mov dword [ ds : di ], ' '
11FF: C7 45 04 20 20 mov word [ ds : di + 4 ], ' '
1204: E8 1E F6 call decode
1207: BE 71 05 mov si, RamdiskSize_msg
120A: E8 37 F6 call printplain
120D: 61 popa
120E: 39 5E C2 cmp free_ad_memory, bx
1211: 0F 86 80 07 jbe ._not_memory_in_sys?0iL
1215: 66 0F B7 C3 movzx eax, bx
1219: 66 C1 E0 0A shl eax, 10
121D: 66 89 46 BA mov save_ramdisksize, eax
1221: 8B 7E F4 mov di, point_default
1224: 8B 4E FA mov cx, save_cx_d
1227: E8 49 F6 call get_firs_sym
122A: 85 C9 test cx, cx
122C: 0F 84 5D 07 jz ._end_parse_FRS
1230: 3C 52 cmp al, 'R'
1232: 75 F3 jnz .start_g_tpe_RFS
1234: 89 CB mov bx, cx
1236: 89 F8 mov ax, di
1238: BE E4 07 mov si, parse_RamdiskFS
123B: B9 09 00 mov cx, parse_RamdiskFS_e - parse_RamdiskFS
123E: F3 repe
123F: A6 cmpsb
1240: 0F 85 38 07 jnz .start_g_tpe_RFS_rest_v
1244: 83 EB 09 sub bx, parse_RamdiskFS_e - parse_RamdiskFS
1247: 01 CB add bx, cx
1249: 89 D9 mov cx, bx
124B: F7 46 F8 04 00 test status_flag, flag_found_GTRFMS
1250: 74 00 jz .correct_is_not_set_FRS
1252: B8 20 3D mov ax, 0x3d20
1255: F3 repe
1256: AE scasb
1257: 85 C9 test cx, cx
1259: 0F 84 26 07 jz .end_get_FRS_ERROR_1
125D: 26 3A 65 FF cmp ah, byte [ es : di - 1 ]
1261: 75 C4 jnz .start_g_tpe_RFS
1263: F3 repe
1264: AE scasb
1265: 41 inc cx
1266: 4F dec di
1267: 89 CB mov bx, cx
1269: 89 F8 mov ax, di
126B: BE 08 08 mov si, parse_RFS_FAT
126E: B9 03 00 mov cx, parse_RFS_FAT_e - parse_RFS_FAT
1271: F3 repe
1272: A6 cmpsb
1273: 0F 85 F7 06 jnz .krfs_cmp
1277: 8B 7E F4 mov di, point_default
127A: 8B 4E FA mov cx, save_cx_d
127D: E8 F3 F5 call get_firs_sym
1280: 85 C9 test cx, cx
1282: 74 54 jz .end_RamdiskSector
1284: 3C 52 cmp al, 'R'
1286: 75 F5 jnz .start_RamdiskSector
1288: 89 CB mov bx, cx
128A: 89 F8 mov ax, di
128C: BE ED 07 mov si, parse_RamdiskSector
128F: B9 0D 00 mov cx, parse_RamdiskSector_e - parse_RamdiskSector
1292: F3 repe
1293: A6 cmpsb
1294: 75 3C jnz .RamdiskSector_rest_val
1296: 83 EB 0D sub bx, parse_RamdiskSector_e - parse_RamdiskSector
1299: 01 CB add bx, cx
129B: 89 D9 mov cx, bx
129D: F7 46 F8 08 00 test status_flag, flag_found_RamdiskSector
12A2: 74 00 jz .correct_is_not_set_RamdiskSector
12A4: B8 20 3D mov ax, 0x3d20
12A7: F3 repe
12A8: AE scasb
12A9: E3 2D jcxz .end_get_RamS_ERROR_1
12AB: 26 3A 65 FF cmp ah, byte [ es : di - 1 ]
12AF: 75 CC jnz .start_RamdiskSector
12B1: F3 repe
12B2: AE scasb
12B3: 41 inc cx
12B4: 4F dec di
12B5: 31 DB xor bx, bx
12B7: B9 04 00 mov cx, 4
12BA: 26 0F B6 05 movzx ax, byte [ es : di ]
12BE: 3C 30 cmp al, '0'
12C0: 72 16 jb .end_RamdiskSector
12C2: 3C 39 cmp al, '9'
12C4: 77 12 ja .end_RamdiskSector
12C6: 6B DB 0A imul bx, 10
12C9: 34 30 xor al, 0x30
12CB: 01 C3 add bx, ax
12CD: 47 inc di
12CE: E2 EA loop @b
12D0: EB 06 jmp .end_RamdiskSector
12D2: 89 D9 mov cx, bx
12D4: 89 C7 mov di, ax
12D6: EB A5 jmp .start_RamdiskSector
12D8: 89 D8 mov ax, bx
12DA: 60 pusha
12DB: 66 0F B7 C3 movzx eax, bx
12DF: B9 0A 00 mov cx, 0x0a
12E2: BF 8E 05 mov di, RamdiskSector_msg
12E5: 66 C7 05 20 20 20 20 mov dword [ ds : di ], ' '
12EC: 66 C7 45 04 20 20 20 20 mov dword [ ds : di + 4 ], ' '
12F4: E8 2E F5 call decode
12F7: BE 8E 05 mov si, RamdiskSector_msg
12FA: E8 47 F5 call printplain
12FD: 61 popa
12FE: 3D 00 10 cmp ax, 4096
1301: 77 04 ja .RS1?0sn
1303: 85 C0 test ax, ax
1305: 75 06 jnz @f
1307: C7 06 87 1A 00 02 mov word [ fat12_buffer.BPB_BytsPerSec ], 512
130D: A3 87 1A mov word [ fat12_buffer.BPB_BytsPerSec ], ax
1310: 8B 7E F4 mov di, point_default
1313: 8B 4E FA mov cx, save_cx_d
1316: E8 5A F5 call get_firs_sym
1319: 85 C9 test cx, cx
131B: 74 47 jz .end_RamdiskCluster
131D: 3C 52 cmp al, 'R'
131F: 75 F5 jnz .start_RamdiskCluster
1321: 89 CB mov bx, cx
1323: 89 F8 mov ax, di
1325: BE FA 07 mov si, parse_RamdiskCluster
1328: B9 0E 00 mov cx, parse_RamdiskCluster_e - parse_RamdiskCluster
132B: F3 repe
132C: A6 cmpsb
132D: 75 2F jnz .RamdiskCluster_rest_val
132F: 83 EB 0E sub bx, parse_RamdiskCluster_e - parse_RamdiskCluster
1332: 01 CB add bx, cx
1334: 89 D9 mov cx, bx
1336: F7 46 F8 16 00 test status_flag, flag_found_RamdiskCluster
133B: 74 00 jz .correct_is_not_set_RamdiskCluster
133D: B8 20 3D mov ax, 0x3d20
1340: F3 repe
1341: AE scasb
1342: E3 20 jcxz .end_get_RamSC_ERROR_1
1344: 26 3A 65 FF cmp ah, byte [ es : di - 1 ]
1348: 75 CC jnz .start_RamdiskCluster
134A: F3 repe
134B: AE scasb
134C: 41 inc cx
134D: 4F dec di
134E: 26 0F B6 05 movzx ax, byte [ es : di ]
1352: 3C 30 cmp al, '0'
1354: 72 0E jb .end_RamdiskCluster
1356: 3C 39 cmp al, '9'
1358: 77 0A ja .end_RamdiskCluster
135A: 34 30 xor al, 0x30
135C: EB 06 jmp .end_RamdiskCluster
135E: 89 D9 mov cx, bx
1360: 89 C7 mov di, ax
1362: EB B2 jmp .start_RamdiskCluster
1364: 60 pusha
1365: B9 0A 00 mov cx, 0x0a
1368: BF AA 05 mov di, RamdiskCluster_msg
136B: E8 B7 F4 call decode
136E: BE AA 05 mov si, RamdiskCluster_msg
1371: E8 D0 F4 call printplain
1374: 61 popa
1375: 3C 80 cmp al, 128
1377: 77 6B ja @f
1379: A2 89 1A mov byte [ fat12_buffer.BPB_SecPerClus ], al
137C: 66 0F B7 06 87 1A movzx eax, word [ fat12_buffer.BPB_BytsPerSec ]
1382: 66 0F B6 1E 89 1A movzx ebx, byte [ fat12_buffer.BPB_SecPerClus ]
1388: 66 0F AF D8 imul ebx, eax
138C: 66 8B 46 BA mov eax, save_ramdisksize
1390: 66 99 cdq
1392: 66 F7 FB idiv ebx
1395: 66 3D F5 0F 00 00 cmp eax, 4085
139B: 0F 82 8E 00 jb .fat12?0so
139F: 66 3D F5 FF 00 00 cmp eax, 65525
13A5: 72 18 jb .fat16?0sp
13A7: C7 46 B4 20 00 mov set_ramfs, 32
13AC: C7 06 8A 1A 20 00 mov word [ fat12_buffer.BPB_RsvdSecCnt ], 32
13B2: 66 31 C0 xor eax, eax
13B5: A3 8D 1A mov word [ fat12_buffer.BPB_RootEntCnt ], ax
13B8: A3 8F 1A mov word [ fat12_buffer.BPB_TotSec16 ], ax
13BB: 66 A3 9C 1A mov dword [ fat12_buffer.BPB_TotSec32 ], eax
13BF: EB FE jmp $
13C1: C7 46 B4 10 00 mov set_ramfs, 16
13C6: 66 0F B6 1E 89 1A movzx ebx, byte [ fat12_buffer.BPB_SecPerClus ]
13CC: 66 0F AF C3 imul eax, ebx
13D0: 66 3D 00 00 01 00 cmp eax, 0x10000
13D6: 73 0C jae @f
13D8: A3 8F 1A mov word [ fat12_buffer.BPB_TotSec16 ], ax
13DB: 66 C7 06 9C 1A 00 00 00 00 mov dword [ fat12_buffer.BPB_TotSec32 ], 0
13E4: 66 B8 E0 00 00 00 mov eax, root_dir_entry_count
13EA: A3 8D 1A mov word [ fat12_buffer.BPB_RootEntCnt ], ax
13ED: 66 0F B7 1E 87 1A movzx ebx, word [ fat12_buffer.BPB_BytsPerSec ]
13F3: 66 6B C0 20 imul eax, 32
13F7: 66 01 D8 add eax, ebx
13FA: 66 48 dec eax
13FC: 66 99 cdq
13FE: 66 F7 FB idiv ebx
1401: 66 0F B7 1E 8A 1A movzx ebx, word [ fat12_buffer.BPB_RsvdSecCnt ]
1407: 66 01 C3 add ebx, eax
140A: 66 0F B7 06 8F 1A movzx eax, word [ fat12_buffer.BPB_TotSec16 ]
1410: 66 29 D8 sub eax, ebx
1413: 66 C1 E7 08 shl edi, 8
1417: 66 0F B6 0E 8C 1A movzx ecx, byte [ fat12_buffer.BPB_NumFATs ]
141D: 66 01 CF add edi, ecx
1420: 66 01 F8 add eax, edi
1423: 66 48 dec eax
1425: 66 99 cdq
1427: 66 F7 FF idiv edi
142A: A3 92 1A mov word [ fat12_buffer.BPB_FATSz16 ], ax
142D: C7 46 B4 0C 00 mov set_ramfs, 12
1432: 66 0F B6 1E 89 1A movzx ebx, byte [ fat12_buffer.BPB_SecPerClus ]
1438: 66 0F AF C3 imul eax, ebx
143C: 66 3D 00 00 01 00 cmp eax, 0x10000
1442: 73 0C jae @f
1444: A3 8F 1A mov word [ fat12_buffer.BPB_TotSec16 ], ax
1447: 66 C7 06 9C 1A 00 00 00 00 mov dword [ fat12_buffer.BPB_TotSec32 ], 0
1450: 66 B8 E0 00 00 00 mov eax, root_dir_entry_count
1456: A3 8D 1A mov word [ fat12_buffer.BPB_RootEntCnt ], ax
1459: 66 0F B7 06 8F 1A movzx eax, word [ fat12_buffer.BPB_TotSec16 ]
145F: 66 6B C0 0C imul eax, 12
1463: 66 C1 E8 03 shr eax, 3
1467: 66 0F B7 1E 87 1A movzx ebx, word [ fat12_buffer.BPB_BytsPerSec ]
146D: 66 99 cdq
146F: 66 F7 FB idiv ebx
1472: 40 inc ax
1473: A3 92 1A mov word [ fat12_buffer.BPB_FATSz16 ], ax
1476: A1 92 1A mov ax, word [ fat12_buffer.BPB_FATSz16 ]
1479: 0F B6 1E 8C 1A movzx bx, byte [ fat12_buffer.BPB_NumFATs ]
147E: 0F AF C3 imul ax, bx
1481: 8B 1E 8D 1A mov bx, word [ fat12_buffer.BPB_RootEntCnt ]
1485: C1 EB 04 shr bx, 4
1488: 01 D8 add ax, bx
148A: 89 5E B0 mov size_root_dir, bx
148D: 0F B6 1E 8A 1A movzx bx, byte [ fat12_buffer.BPB_RsvdSecCnt ]
1492: 01 D8 add ax, bx
1494: 89 46 AE mov firstDataSect, ax
1497: 8B 1E 8F 1A mov bx, word [ fat12_buffer.BPB_TotSec16 ]
149B: 29 C3 sub bx, ax
149D: 89 D8 mov ax, bx
149F: 0F B6 1E 89 1A movzx bx, byte [ fat12_buffer.BPB_SecPerClus ]
14A4: 99 cwd
14A5: F7 FB idiv bx
14A7: 89 46 AC mov DataClasters, ax
14AA: 60 pusha
14AB: 8B 46 AE mov ax, firstDataSect
14AE: B9 0A 00 mov cx, 0x0a
14B1: BF 44 06 mov di, firstDataSect_msg
14B4: E8 6E F3 call decode
14B7: BE 44 06 mov si, firstDataSect_msg
14BA: E8 87 F3 call printplain
14BD: 8B 46 B0 mov ax, size_root_dir
14C0: B9 0A 00 mov cx, 0x0a
14C3: BF 79 06 mov di, size_root_dir_msg
14C6: E8 5C F3 call decode
14C9: BE 79 06 mov si, size_root_dir_msg
14CC: E8 75 F3 call printplain
14CF: 8B 46 AC mov ax, DataClasters
14D2: B9 0A 00 mov cx, 0x0a
14D5: BF 9B 06 mov di, DataClasters_msg
14D8: E8 4A F3 call decode
14DB: BE 9B 06 mov si, DataClasters_msg
14DE: E8 63 F3 call printplain
14E1: 61 popa
14E2: A0 91 1A mov al, byte [ fat12_buffer.BPB_Media ]
14E5: 1E push ds
14E6: 8B 7E C4 mov di, info_real_mode_size
14E9: 81 C7 00 10 add di, 0x1000
14ED: 57 push di
14EE: 31 FF xor di, di
14F0: 89 7E AA mov point_to_free_root, di
14F3: 1F pop ds
14F4: 88 05 mov byte [ di ], al
14F6: 83 C8 FF or ax, - 1
14F9: 47 inc di
14FA: 89 05 mov word [ di ], ax
14FC: 1F pop ds
14FD: C7 46 B2 03 00 mov point_next_fat_str, 3
1502: 60 pusha
1503: 8B 46 B2 mov ax, point_next_fat_str
1506: B9 0A 00 mov cx, 0x0a
1509: BF DA 05 mov di, fat_create_msg
150C: E8 16 F3 call decode
150F: BE DA 05 mov si, fat_create_msg
1512: E8 2F F3 call printplain
1515: 61 popa
1516: B8 7C 1A mov ax, fat12_buffer
1519: BE 3C 1A mov si, table_15_87
151C: 01 44 12 add word [ si + 8 * 2 + 2 ], ax
151F: 06 push es
1520: 1E push ds
1521: 07 pop es
1522: B9 1F 00 mov cx, 31
1525: B4 87 mov ah, 0x87
1527: CD 15 int 0x15
1529: 07 pop es
152A: 60 pusha
152B: 8B 44 12 mov ax, word [ si + 8 * 2 + 2 ]
152E: B9 0A 00 mov cx, 0x0a
1531: BF 0E 06 mov di, BPB_msg
1534: E8 EE F2 call decode
1537: BE 0E 06 mov si, BPB_msg
153A: E8 07 F3 call printplain
153D: 61 popa
153E: 8B 7E F4 mov di, point_default
1541: 8B 4E FA mov cx, save_cx_d
1544: C7 46 A6 00 00 mov data_offset, 0
1549: E8 27 F3 call get_firs_sym
154C: 85 C9 test cx, cx
154E: 0F 84 B3 03 jz ._end?1D2
1552: 3C 52 cmp al, 'R'
1554: 75 F3 jnz .start_loop?1D1
1556: 89 CB mov bx, cx
1558: 89 F8 mov ax, di
155A: BE 1A 08 mov si, parse_RamdiskFile
155D: B9 0B 00 mov cx, parse_RamdiskFile_e - parse_RamdiskFile
1560: F3 repe
1561: A6 cmpsb
1562: 0F 85 98 03 jnz .rest_value_loop?1D3
1566: 83 EB 0B sub bx, parse_RamdiskFile_e - parse_RamdiskFile
1569: 01 CB add bx, cx
156B: 89 D9 mov cx, bx
156D: B8 20 3D mov ax, 0x3d20
1570: F3 repe
1571: AE scasb
1572: 66 85 C9 test ecx, ecx
1575: 0F 84 85 03 jz .rest_value_loop?1D3
1579: 26 3A 65 FF cmp ah, byte [ es : di - 1 ]
157D: 0F 85 7D 03 jnz .rest_value_loop?1D3
1581: F3 repe
1582: AE scasb
1583: 41 inc cx
1584: 4F dec di
1585: 89 7E A2 mov save_di_RAMDISK, di
1588: 89 4E A0 mov save_cx_RAMDISK, cx
158B: 26 8A 05 mov al, byte [ es : di ]
158E: 3C 2C cmp al, ','
1590: 74 04 jz .found_end_str
1592: 47 inc di
1593: 49 dec cx
1594: 75 F5 jnz @b
1596: 89 7E A8 mov point_to_dest_file_name, di
1599: 47 inc di
159A: BE BA 1A mov si, shot_name_fat
159D: 83 4E A4 FF or first_input, - 1
15A1: B9 0B 00 mov cx, 11
15A4: 26 8A 05 mov al, byte [ es : di ]
15A7: 3C 0A cmp al, 0xa
15A9: 74 7D jz .st4_s?1GP
15AB: 3C 0D cmp al, 0xd
15AD: 74 79 jz .st4_s?1GP
15AF: 3C 20 cmp al, 0x20
15B1: 74 75 jz .st4_s?1GP
15B3: 3C 20 cmp al, 0x20
15B5: 72 7A jb .error?1GK
15B7: 3C 22 cmp al, 0x22
15B9: 74 76 jz .error?1GK
15BB: 3C 2A cmp al, 0x2a
15BD: 74 72 jz .error?1GK
15BF: 3C 2B cmp al, 0x2b
15C1: 74 6E jz .error?1GK
15C3: 3C 2C cmp al, 0x2c
15C5: 74 6A jz .error?1GK
15C7: 3C 2F cmp al, 0x2F
15C9: 74 66 jz .error?1GK
15CB: 3C 3A cmp al, 0x3a
15CD: 74 62 jz .error?1GK
15CF: 3C 3B cmp al, 0x3b
15D1: 74 5E jz .error?1GK
15D3: 3C 3C cmp al, 0x3c
15D5: 74 5A jz .error?1GK
15D7: 3C 3D cmp al, 0x3d
15D9: 74 56 jz .error?1GK
15DB: 3C 3E cmp al, 0x3E
15DD: 74 52 jz .error?1GK
15DF: 3C 3F cmp al, 0x3F
15E1: 74 4E jz .error?1GK
15E3: 3C 5B cmp al, 0x5b
15E5: 74 4A jz .error?1GK
15E7: 3C 5C cmp al, 0x5c
15E9: 74 46 jz .error?1GK
15EB: 3C 5D cmp al, 0x5d
15ED: 74 42 jz .error?1GK
15EF: 3C 7C cmp al, 0x7c
15F1: 74 3E jz .error?1GK
15F3: 83 7E A4 FF cmp first_input, - 1
15F7: 75 08 jnz .next_step?1GJ
15F9: 83 66 A4 00 and first_input, 0
15FD: 3C 2E cmp al, '.'
15FF: 74 30 jz .error?1GK
1601: 3C 2E cmp al, 0x2e
1603: 75 13 jnz .st2?1GM
1605: B0 20 mov al, ' '
1607: 80 F9 03 cmp cl, 3
160A: 76 0C jbe .st2?1GM
160C: 88 04 mov byte [ si ], al
160E: 46 inc si
160F: 49 dec cx
1610: 83 F9 03 cmp cx, 3
1613: 77 F7 ja .st3?1GO
1615: 47 inc di
1616: EB 8C jmp @b
1618: 3C 60 cmp al, 0x60
161A: 76 02 jbe .st2_l?1GN
161C: 34 20 xor al, 0x20
161E: 88 04 mov byte [ si ], al
1620: 47 inc di
1621: 46 inc si
1622: E2 80 loop @b
1624: 31 C0 xor ax, ax
1626: EB 0C jmp @f
1628: B0 20 mov al, ' '
162A: 88 04 mov byte [ si ], al
162C: 46 inc si
162D: E2 FB loop .st4?1GQ
162F: EB F3 jmp .st5?1GR
1631: 83 C8 FF or ax, - 1
1634: 60 pusha
1635: B9 0A 00 mov cx, 0x0a
1638: BF F5 06 mov di, convertion_file_name_msg
163B: E8 E7 F1 call decode
163E: BE F5 06 mov si, convertion_file_name_msg
1641: E8 00 F2 call printplain
1644: BE BA 1A mov si, shot_name_fat
1647: C6 44 0C 00 mov byte [ si + 12 ], 0
164B: E8 F6 F1 call printplain
164E: 61 popa
164F: 85 C0 test ax, ax
1651: 75 39 jnz .exit?1GI
1653: BE BA 1A mov si, shot_name_fat
1656: 8B 7E AE mov di, firstDataSect
1659: 2B 7E B0 sub di, size_root_dir
165C: C1 E7 09 shl di, 9
165F: BA E0 00 mov dx, root_dir_entry_count
1662: 8B 46 C4 mov ax, info_real_mode_size
1665: 05 00 10 add ax, 0x1000
1668: 8E E8 mov gs, ax
166A: B9 0B 00 mov cx, 11
166D: 8A 00 mov al, byte [ ds : si + bx ]
166F: 65 8A 21 mov ah, byte [ gs : di + bx ]
1672: 43 inc bx
1673: 38 C4 cmp ah, al
1675: 75 07 jnz .no_equal?1GH
1677: E2 F4 loop @b
1679: 83 C8 FF or ax, - 1
167C: EB 0E jmp .exit?1GI
167E: B9 0B 00 mov cx, 11
1681: 31 DB xor bx, bx
1683: 83 C7 20 add di, 32
1686: 4A dec dx
1687: 75 E4 jnz @b
1689: 83 E0 00 and ax, 0
168C: 60 pusha
168D: B9 0A 00 mov cx, 0x0a
1690: BF B9 06 mov di, check_name_fat_msg
1693: 66 C7 05 20 20 20 20 mov dword [ di ], ' '
169A: C7 45 04 20 20 mov word [ di + 4 ], ' '
169F: E8 83 F1 call decode
16A2: BE B9 06 mov si, check_name_fat_msg
16A5: E8 9C F1 call printplain
16A8: 61 popa
16A9: 8B 7E A2 mov di, save_di_RAMDISK
16AC: 8B 4E A0 mov cx, save_cx_RAMDISK
16AF: 84 C0 test al, al
16B1: 0F 85 94 FE jnz .start_loop?1D1
16B5: 26 66 FF 75 FA push dword [ es : di - 6 ]
16BA: 8D 75 FA lea si, [ di - 6 ]
16BD: 26 FF 75 FE push word [ es : di - 2 ]
16C1: 57 push di
16C2: 31 C0 xor ax, ax
16C4: 26 89 45 FA mov word [ es : di - 6 ], ax
16C8: 8B 46 C4 mov ax, info_real_mode_size
16CB: 26 89 45 FC mov word [ es : di - 4 ], ax
16CF: 26 C7 45 FE 10 00 mov word [ es : di - 2 ], 16
16D5: 8B 7E A8 mov di, point_to_dest_file_name
16D8: 26 FF 35 push word [ es : di ]
16DB: 51 push cx
16DC: 31 C0 xor ax, ax
16DE: 26 89 05 mov word [ es : di ], ax
16E1: 57 push di
16E2: 89 F7 mov di, si
16E4: 40 inc ax
16E5: 56 push si
16E6: 06 push es
16E7: 55 push bp
16E8: 06 push es
16E9: 1F pop ds
16EA: 0E push cs
16EB: 07 pop es
16EC: 26 FF 1E DC 0A call far dword [ es : loader_callback ]
16F1: 0E push cs
16F2: 1F pop ds
16F3: 5D pop bp
16F4: 07 pop es
16F5: 5E pop si
16F6: 83 FB 02 cmp bx, 2
16F9: 0F 87 01 02 ja .error?1D4
16FD: 89 5E 9E mov status_flag_loader_f, bx
1700: 66 C1 E2 10 shl edx, 16
1704: 89 C2 mov dx, ax
1706: 66 89 56 B6 mov save_file_size, edx
170A: 66 89 D0 mov eax, edx
170D: 5F pop di
170E: 59 pop cx
170F: 26 8F 05 pop word [ es : di ]
1712: 5F pop di
1713: 26 8F 45 FE pop word [ es : di - 2 ]
1717: 26 66 8F 45 FA pop dword [ es : di - 6 ]
171C: 60 pusha
171D: B9 0A 00 mov cx, 0x0a
1720: BF C1 05 mov di, RamdiskFile_msg
1723: 66 C7 05 20 20 20 20 mov dword [ ds : di ], ' '
172A: E8 F8 F0 call decode
172D: BE C1 05 mov si, RamdiskFile_msg
1730: E8 11 F1 call printplain
1733: 61 popa
1734: 06 push es
1735: 8B 46 C4 mov ax, info_real_mode_size
1738: 05 00 10 add ax, 0x1000
173B: 8E C0 mov es, ax
173D: 8B 7E AE mov di, firstDataSect
1740: 2B 7E B0 sub di, size_root_dir
1743: C1 E7 09 shl di, 9
1746: 03 7E AA add di, point_to_free_root
1749: BE BA 1A mov si, shot_name_fat
174C: B9 0B 00 mov cx, 11
174F: AC lodsb
1750: AA stosb
1751: E2 FC loop @b
1753: 31 C0 xor ax, ax
1755: B4 08 mov ah, ATTR_VOLUME_ID
1757: 26 89 05 mov word [ es : di ], ax
175A: 83 C7 02 add di, 2
175D: 26 C6 05 64 mov byte [ es : di ], 100
1761: 47 inc di
1762: 26 C7 05 2B 03 mov word [ es : di ], 0x032b
1767: 83 C7 02 add di, 2
176A: 26 C7 05 00 00 mov word [ es : di ], 0x0
176F: 83 C7 02 add di, 2
1772: 26 C7 05 2B 03 mov word [ es : di ], 0x032b
1777: 83 C7 02 add di, 2
177A: 26 C7 05 00 00 mov word [ es : di ], 0x0
177F: 83 C7 02 add di, 2
1782: 26 C7 05 00 00 mov word [ es : di ], 0x0
1787: 83 C7 02 add di, 2
178A: 26 C7 05 2B 03 mov word [ es : di ], 0x032b
178F: 83 C7 02 add di, 2
1792: 8B 46 B2 mov ax, point_next_fat_str
1795: 26 89 05 mov word [ es : di ], ax
1798: 83 C7 02 add di, 2
179B: 57 push di
179C: 89 C3 mov bx, ax
179E: D1 EB shr bx, 1
17A0: 01 D8 add ax, bx
17A2: 8B 1E 87 1A mov bx, word [ fat12_buffer.BPB_BytsPerSec ]
17A6: 99 cwd
17A7: F7 FB idiv bx
17A9: 89 C6 mov si, ax
17AB: 66 0F B7 06 87 1A movzx eax, word [ fat12_buffer.BPB_BytsPerSec ]
17B1: 66 0F B6 1E 89 1A movzx ebx, byte [ fat12_buffer.BPB_SecPerClus ]
17B7: 66 0F AF C3 imul eax, ebx
17BB: 66 8B 5E B6 mov ebx, save_file_size
17BF: 66 29 C3 sub ebx, eax
17C2: 66 39 C3 cmp ebx, eax
17C5: 76 29 jbe .eof_file?1US
17C7: FF 46 B2 inc point_next_fat_str
17CA: 8B 4E B2 mov cx, point_next_fat_str
17CD: 89 C2 mov dx, ax
17CF: D1 EA shr dx, 1
17D1: 01 D1 add cx, dx
17D3: F7 C6 01 00 test si, 0x1
17D7: 74 0B jz .step2?1UP
17D9: C1 E1 04 shl cx, 4
17DC: 26 89 0C mov word [ es : si ], cx
17DF: 46 inc si
17E0: 01 C1 add cx, ax
17E2: EB DB jmp @b
17E4: 81 E1 FF 0F and cx, 0x0FFF
17E8: 26 89 0C mov word [ es : si ], cx
17EB: 46 inc si
17EC: 01 C1 add cx, ax
17EE: EB CF jmp @b
17F0: B9 FF 0F mov cx, 0x0fff
17F3: F7 C6 01 00 test si, 0x1
17F7: 74 08 jz .step3?1UQ
17F9: C1 E1 04 shl cx, 4
17FC: 26 89 0C mov word [ es : si ], cx
17FF: EB 07 jmp .end?1UR
1801: 81 E1 FF 0F and cx, 0x0FFF
1805: 26 89 0C mov word [ es : si ], cx
1808: FF 46 B2 inc point_next_fat_str
180B: 5F pop di
180C: 66 8B 46 B6 mov eax, save_file_size
1810: 26 66 89 05 mov dword [ es : di ], eax
1814: 66 60 pushad
1816: 8B 7E AE mov di, firstDataSect
1819: 2B 7E B0 sub di, size_root_dir
181C: C1 E7 09 shl di, 9
181F: 03 7E AA add di, point_to_free_root
1822: BE C6 1A mov si, dest_name_fat
1825: B9 0B 00 mov cx, 11
1828: 26 8A 05 mov al, byte [ es : di ]
182B: 47 inc di
182C: 88 04 mov byte [ ds : si ], al
182E: 46 inc si
182F: E2 F7 loop @b
1831: 31 C0 xor ax, ax
1833: 88 04 mov byte [ si ], al
1835: BE C6 1A mov si, dest_name_fat
1838: E8 09 F0 call printplain
183B: 66 61 popad
183D: 83 46 AA 20 add point_to_free_root, 32
1841: 07 pop es
1842: 8B 46 C4 mov ax, info_real_mode_size
1845: BE 3C 1A mov si, table_15_87
1848: 89 44 12 mov word [ si + 8 * 2 + 2 ], ax
184B: 66 0F B7 46 AE movzx eax, firstDataSect
1850: 66 0F B7 56 A6 movzx edx, data_offset
1855: 66 01 D0 add eax, edx
1858: 66 0F B7 1E 87 1A movzx ebx, word [ fat12_buffer.BPB_BytsPerSec ]
185E: 66 0F B6 16 89 1A movzx edx, byte [ fat12_buffer.BPB_SecPerClus ]
1864: 0F AF DA imul bx, dx
1867: 66 53 push ebx
1869: 66 0F AF C3 imul eax, ebx
186D: 60 pusha
186E: B9 0A 00 mov cx, 0x0a
1871: BF 07 04 mov di, show_db1
1874: E8 AE EF call decode
1877: BE 07 04 mov si, show_db1
187A: E8 C7 EF call printplain
187D: 61 popa
187E: B2 10 mov dl, 0x10
1880: 66 3D 00 00 01 00 cmp eax, 0x00010000
1886: 72 0A jb @f
1888: 66 2D 00 00 01 00 sub eax, 0x00010000
188E: FE C2 inc dl
1890: EB EE jmp @b
1892: 88 54 1B mov byte [ si + 8 * 3 + 3 ], dl
1895: 89 44 1A mov word [ si + 8 * 3 + 2 ], ax
1898: 66 8B 4E B6 mov ecx, save_file_size
189C: 66 81 F9 FF FF 00 00 cmp ecx, 0x0000ffff
18A3: 76 0A jbe .correct_on_byte?1cJ
18A5: 66 B9 00 00 01 00 mov ecx, 0x00010000
18AB: 66 29 4E B6 sub save_file_size, ecx
18AF: 66 58 pop eax
18B1: 66 51 push ecx
18B3: FF 46 A6 inc data_offset
18B6: 66 39 C8 cmp eax, ecx
18B9: 73 05 jae @f
18BB: 66 29 C1 sub ecx, eax
18BE: EB F3 jmp @b
18C0: 66 59 pop ecx
18C2: 66 F7 C1 01 00 00 00 test ecx, 0x1
18C9: 74 02 jz .st1?1cI
18CB: 66 41 inc ecx
18CD: 66 D1 E9 shr ecx, 1
18D0: 06 push es
18D1: 1E push ds
18D2: 07 pop es
18D3: B4 87 mov ah, 0x87
18D5: CD 15 int 0x15
18D7: 07 pop es
18D8: 60 pusha
18D9: B9 0A 00 mov cx, 0x0a
18DC: BF 46 07 mov di, return_code_af_move
18DF: E8 43 EF call decode
18E2: BE 46 07 mov si, return_code_af_move
18E5: E8 5C EF call printplain
18E8: 61 popa
18E9: 83 7E 9E 01 cmp status_flag_loader_f, 0x1
18ED: 75 00 jnz @f
18EF: 8B 7E A2 mov di, save_di_RAMDISK
18F2: 8B 4E A0 mov cx, save_cx_RAMDISK
18F5: 60 pusha
18F6: 31 C0 xor ax, ax
18F8: CD 16 int 0x16
18FA: 61 popa
18FB: E9 4B FC jmp .start_loop?1D1
18FE: 89 C7 mov di, ax
1900: 89 D9 mov cx, bx
1902: E9 44 FC jmp .start_loop?1D1
1905: 8B 46 C4 mov ax, info_real_mode_size
1908: 05 00 10 add ax, 0x1000
190B: BE 3C 1A mov si, table_15_87
190E: 89 44 12 mov word [ si + 8 * 2 + 2 ], ax
1911: B8 00 02 mov ax, 512
1914: 89 44 1A mov word [ si + 8 * 3 + 2 ], ax
1917: 66 0F B7 0E 92 1A movzx ecx, word [ fat12_buffer.BPB_FATSz16 ]
191D: 0F B6 1E 8C 1A movzx bx, byte [ fat12_buffer.BPB_NumFATs ]
1922: 0F AF CB imul cx, bx
1925: 03 4E B0 add cx, size_root_dir
1928: 66 C1 E1 09 shl ecx, 9
192C: 66 F7 C1 01 00 00 00 test ecx, 0x1
1933: 74 02 jz .st1?1ho
1935: 66 41 inc ecx
1937: 66 D1 E9 shr ecx, 1
193A: 06 push es
193B: 1E push ds
193C: 07 pop es
193D: B4 87 mov ah, 0x87
193F: CD 15 int 0x15
1941: 07 pop es
1942: 60 pusha
1943: B9 0A 00 mov cx, 0x0a
1946: BF 77 07 mov di, return_code_af_fat_m
1949: E8 D9 EE call decode
194C: BE 77 07 mov si, return_code_af_fat_m
194F: E8 F2 EE call printplain
1952: 61 popa
1953: 60 pusha
1954: B9 0A 00 mov cx, 0x0a
1957: BF 07 04 mov di, show_db1
195A: E8 C8 EE call decode
195D: BE 07 04 mov si, show_db1
1960: E8 E1 EE call printplain
1963: 61 popa
1964: 60 pusha
1965: BE 21 07 mov si, make_fat12_RFS_msg
1968: E8 D9 EE call printplain
196B: 61 popa
196C: EB 1F jmp ._end_parse_FRS
196E: 89 D9 mov cx, bx
1970: 89 C7 mov di, ax
1972: BE 0B 08 mov si, parse_RFS_KRFS
1975: B9 04 00 mov cx, parse_RFS_KRFS_e - parse_RFS_KRFS
1978: F3 repe
1979: A6 cmpsb
197A: EB 11 jmp ._end_parse_FRS
197C: 89 D9 mov cx, bx
197E: 89 C7 mov di, ax
1980: E9 A4 F8 jmp .start_g_tpe_RFS
1983: 83 4E C0 01 or show_errors_sect, show_error_1
1987: EB 04 jmp ._end_parse_FRS
1989: 83 4E C0 02 or show_errors_sect, show_error_2
198D: 60 pusha
198E: BE 34 07 mov si, get_type_FS_msg
1991: E8 B0 EE call printplain
1994: 61 popa
1995: 31 C0 xor ax, ax
1997: CD 16 int 0x16
1999: 8B 7E F4 mov di, point_default
199C: 8B 4E FA mov cx, save_cx_d
199F: E8 D1 EE call get_firs_sym
19A2: 85 C9 test cx, cx
19A4: 0F 84 8E 00 jz ._afterLoaderModule
19A8: 3C 4C cmp al, 'L'
19AA: 75 F3 jnz .start_p_LM
19AC: 89 CB mov bx, cx
19AE: 89 F8 mov ax, di
19B0: BE CD 07 mov si, parse_LoaderModule
19B3: B9 0C 00 mov cx, parse_LoaderModule_e - parse_LoaderModule
19B6: F3 repe
19B7: A6 cmpsb
19B8: 75 75 jnz .rest_value_loop_LM
19BA: 83 EB 0C sub bx, parse_LoaderModule_e - parse_LoaderModule
19BD: 01 CB add bx, cx
19BF: 89 D9 mov cx, bx
19C1: F7 46 F8 01 00 test status_flag, flag_found_LM
19C6: 74 00 jz .correct_is_not_set_LM
19C8: B8 20 3D mov ax, 0x3d20
19CB: F3 repe
19CC: AE scasb
19CD: E3 60 jcxz .rest_value_loop_LM
19CF: 26 3A 65 FF cmp ah, byte [ es : di - 1 ]
19D3: 75 5A jnz .rest_value_loop_LM
19D5: F3 repe
19D6: AE scasb
19D7: 41 inc cx
19D8: 4F dec di
19D9: 26 66 FF 75 FA push dword [ es : di - 6 ]
19DE: 8D 75 FA lea si, [ di - 6 ]
19E1: 26 FF 75 FE push word [ es : di - 2 ]
19E5: 31 C0 xor ax, ax
19E7: 26 89 45 FA mov word [ es : di - 6 ], ax
19EB: 8B 46 C4 mov ax, info_real_mode_size
19EE: 26 89 45 FC mov word [ es : di - 4 ], ax
19F2: 26 C7 45 FE 10 00 mov word [ es : di - 2 ], 16
19F8: 26 8A 05 mov al, byte [ es : di ]
19FB: 3C 20 cmp al, ' '
19FD: 74 0C jz .found_end_str?1mb
19FF: 3C 0A cmp al, 0xa
1A01: 74 08 jz .found_end_str?1mb
1A03: 3C 0D cmp al, 0xd
1A05: 74 04 jz .found_end_str?1mb
1A07: 47 inc di
1A08: 49 dec cx
1A09: 75 ED jnz @b
1A0B: 26 FF 35 push word [ es : di ]
1A0E: 31 C0 xor ax, ax
1A10: 26 89 05 mov word [ es : di ], ax
1A13: 89 F7 mov di, si
1A15: 40 inc ax
1A16: 56 push si
1A17: 06 push es
1A18: 06 push es
1A19: 1F pop ds
1A1A: 0E push cs
1A1B: 07 pop es
1A1C: 26 FF 1E DC 0A call far dword [ es : loader_callback ]
1A21: 0E push cs
1A22: 1F pop ds
1A23: 07 pop es
1A24: 5E pop si
1A25: 85 DB test bx, bx
1A27: 75 03 jnz .error_LM
1A29: 26 FF 2C jmp far dword [ es : si ]
1A2C: E8 91 F0 call error.LoaderModule
1A2F: 89 C7 mov di, ax
1A31: 89 D9 mov cx, bx
1A33: E9 69 FF jmp .start_p_LM
1A36: EB FE jmp $
1A38: E9 6A F1 jmp ini_loaded
1A3C: 00 00 00 00 00 00 00 00 db 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x0, 0x0
1A44: 00 00 00 00 00 00 00 00 db 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x0, 0x0
1A4C: FF FF db 0xff, 0xff
1A4E: 00 10 db 0x0, 0x10
1A50: 00 93 00 00 db 0x00, 0x93, 0x0, 0x0
1A54: FF FF 00 00 10 93 00 00 db 0xff, 0xff, 0x0, 0x00, 0x10, 0x93, 0x0, 0x0
1A5C: 00 00 00 00 00 00 00 00 db 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x0, 0x0
1A64: 00 00 00 00 00 00 00 00 db 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x0, 0x0
1A6C: 00 00 00 00 00 00 00 00 db 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x0, 0x0
1A74: 00 00 00 00 00 00 00 00 db 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x0, 0x0
1A7C: 90 90 90 .BS_jmpBoot db 0x90, 0x90, 0x90
1A7F: 4B 20 53 79 53 20 36 34 .BS_OEMName db 'K SyS 64'
1A87: 00 02 .BPB_BytsPerSec dw 512
1A89: 01 .BPB_SecPerClus db 0x1
1A8A: 01 00 .BPB_RsvdSecCnt dw 0x1
1A8C: 01 .BPB_NumFATs db 0x1
1A8D: 00 02 .BPB_RootEntCnt dw 512
1A8F: 00 00 .BPB_TotSec16 dw 0x0
1A91: F0 .BPB_Media db 0xF0
1A92: 00 00 .BPB_FATSz16 dw 0x0
1A94: 00 00 .BPB_SecPerTrk dw 0x0
1A96: 00 00 .BPB_NumHeads dw 0x0
1A98: 00 00 00 00 .BPB_HiddSec dd 0x0
1A9C: 00 00 00 00 .BPB_TotSec32 dd 0x0
1AA0: 52 .BS_DrvNum db 'R'
1AA1: 00 .BS_Reserved1 db 0x0
1AA2: 29 .BS_BootSig db 0x29
1AA3: 52 46 4B 53 .BS_VolID db 'RFKS'
1AA7: 52 41 4D 20 44 49 53 4B 20 46 53 .BS_VolLab db 'RAM DISK FS'
1AB2: 46 41 54 31 32 20 20 20 .BS_FilSysType db 'FAT12 '
1ABA: shot_name_fat rb 11
1AC5: rb 1
1AC6: dest_name_fat rb 12
1AD2: value_timeout rw 1
1AD4: old_timer rd 1
1AD8: start_timer rd 1
1ADC: timer_ rd 1
1AE0: start_stack rw 1
1AE2: save_bp_from_timer rw 1
3 passes, 0.8 seconds, 6842 bytes.
/kernel/branches/kolibri-ahci/sec_loader/trunk/parse_any.inc
0,0 → 1,686
; Copyright (c) 2009, <Lrz>
; 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.
;*****************************************************************************
 
;тут распологается модуль с помощью которого будут парситься все остальные секции
color_sym_black equ 0
color_sym_blue equ 1
color_sym_green equ 2
color_sym_turquoise equ 3
color_sym_red equ 4
 
color_sym_lightgray equ 7
 
color_sym_lightblue equ 9
color_sym_lettuce equ 10
color_sym_pink equ 12
color_sym_yellow equ 14
 
macro use_any_sec
{
;узнаем работу предыдущего шага т.е. чему = timeout, если он 0, то визуальная часть не будет отображена на дисплее с выбором загрузочных секций.
;иначе мы ее должны отобразить и ждать заявленое время для выбора и конигурирования пукнктов секции от пользователя.
 
if DEBUG
pusha
mov ax, word [value_timeout];идет проверка на наличее значения timeout, для более быстрой работы, этот параметр должен быть уже обработан,т.е. в этом случае при его =0 будет сформирован указатель только на дефолтную секцию, иначе информация будет собрана по всем секциям и составлены указатели в блоке памяти
; mov ax,cx
mov cx, 0x0a
mov di, show_db1
mov dword[ds:di], ' '
mov word [ds:di+4], ' '
call decode
;Show size
mov si, show_db1
call printplain
;
popa
end if
 
test ax, ax
jz .parse_run_only
 
;отобразим полный список всех найденых секций.
if DEBUG
pusha
mov si, show_all_sect
call printplain
popa
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov al, 0xf6 ; Сброс клавиатуры, разрешить сканирование
out 0x60, al
xor cx, cx
.wait_loop: ; variant 2
; reading state of port of 8042 controller
in al, 64h
and al, 00000010b ; ready flag
; wait until 8042 controller is ready
loopnz .wait_loop
 
 
; set keyboard typematic rate & delay
mov al, 0xf3
out 0x60, al
xor cx, cx
@@:
in al, 64h
test al, 2
loopnz @b
mov al, 0
out 0x60, al
xor cx, cx
@@:
in al, 64h
test al, 2
loopnz @b
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; get start time
call gettime
mov dword [start_timer], eax
mov word [timer_], newtimer
mov word [timer_+2], cs
;установить свое прерывание на таймер т.е. код будет перрываться ~18 раз в сек и переходить на обработчик
cli
push 0
pop es
push dword [es:8*4]
pop dword [old_timer]
push dword [timer_]
pop dword [es:8*4]
sti
 
;процедура формирования буфера для скролинга секций
;if DEBUG
; pusha
; mov ax,point_default
; mov ax,cx
; mov cx,0x0a
; mov di,show_db1
; mov dword[ds:di],' '
; mov word [ds:di+4],' '
; call decode
;Show size
; mov si,show_db1
; call printplain
;
; xor ax,ax
; int 0x16
; popa
;end if
;;;;;;;;;;;;;размер предыдущей сеции установим =0
mov save_descript_size, 18
;отобразить black screen
show_bl_sc ;es=0xb800
.show_all_scr:
get_frame_buffer ;es=0x2000
;отображение секций
call show_bl_sc_sect ;es=0xb800
;отобразить активный курсор
.show_active_cursor:
show_act_cursor
show_descript ;макрос по отображению описания секции
 
;отобразить Press any key ....
mov eax, dword [old_timer]
cmp eax, dword [timer_]
jz .interrupt_16
 
show_timer_message
mov word [start_stack], sp
.interrupt_16:
xor ax, ax ;получим информацию о том что нажато
int 0x16
;check on change
mov ebx, dword [old_timer]
cmp ebx, dword [timer_]
jz @f
;restore timer interrupt
cli
push 0
pop es
; mov eax,dword [old_timer] ; восстановим прежднее прерывание
mov [es:8*4], ebx
mov dword [timer_], ebx
sti
push ax
clear_timer_msg
pop ax
@@:
call clean_active_cursor ;clean old cursor ;es=0xb800
 
cmp ah, 0x48 ;реакция системы на события
jz .up
cmp ah, 0x50
jz .down
cmp ah, 0x49
jz .pgup
cmp ah, 0x51
jz .pgdown
cmp ah, 0x47
jz .home
cmp ah, 0x4f
jz .end
 
cmp al, 0xD
jnz .show_active_cursor
 
jmp .end_show_all ;парсинг секции которая указана в point_default
.up:
mov si, point_to_point_def ;значение указателя
add si, 2
lea ax, point_to_hframe
 
cmp si, ax
ja @f
 
mov point_to_point_def, si
mov ax, [si]
mov point_default, ax
jmp .show_active_cursor
@@:
call find_before_sect
jmp .show_all_scr
 
 
 
.down:
mov si, point_to_point_def ;значение указателя
mov ax, point_to_eframe ;указатель на последний элемент
sub si, 2
cmp si, ax
jb @f
 
mov point_to_point_def, si
mov ax, [si]
mov point_default, ax
jmp .show_active_cursor
 
@@:
call find_next_sect
jmp .show_all_scr
 
.pgup:
mov cx, size_show_section
@@:
push cx
call find_before_sect
pop cx
loop @b
jmp .show_all_scr
 
 
.pgdown:
mov cx, size_show_section
@@:
push cx
call find_next_sect
pop cx
loop @b
jmp .show_all_scr
 
.home:
xor di, di
call find_next_sect.h
jmp .show_all_scr
 
.end:
mov di, save_cx
call find_before_sect.e
jmp .show_all_scr
 
 
 
 
; тут мы будем парсить только дефолтную секцию и выполнять ее ничего не предлагая пользователю из диалогов.
.parse_run_only:
if DEBUG
pusha
mov si, no_show_only_w
call printplain
popa
end if
 
 
.end_show_all:
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
;show black screen SL
macro show_bl_sc
{
;;;;;;;;;;;;;;;
;очистим экран и выведем меню
; draw frames
xor ax, ax
if DEBUG
mov ax, 0x0720
end if
push 0xb800
pop es
xor di, di
; draw top
mov cx, 25 * 80
rep stosw
;;;;;;;;;;;;;;;;;;;;;;; show 'Secondary Loader v0.xxx'
mov di, 164
mov si, version
mov cx, version_end-version
mov ah, color_sym_yellow
@@:
lodsb
stosw
loop @b
;;;;;;;;;;;;;;;;;;;;;;; show firm ))
mov di, (2*160-(2*(soft_mes_end-soft_mes+4))) ;286
mov ah, color_sym_pink;color_sym_red
mov al, 'K'
stosw
mov al, ' '
stosw
mov ah, color_sym_lightgray;color_sym_lightblue;color_sym_pink
mov si, soft_mes
mov cx, soft_mes_end- soft_mes
@@:
lodsb
stosw
loop @b
;;;;;;;;;;;;;;;;;;;;;;; show '__________________________'
mov di, 480
mov ah, color_sym_yellow
mov al, 0xC4 ; '─'
mov cx, 61
rep stosw
;;;;;;;;;;;;;;;;;;;;;;; show 'Select section'
mov di, 804
mov si, select_section
mov cx, select_section_end - select_section
mov ah, color_sym_lightgray
@@:
lodsb
stosw
loop @b
;;;;;;;;;;;;;;;;;;;;;;; show 'Section description'
mov di, 880
mov si, section_description
mov cx, section_description_end - section_description
; mov ah,color_sym_lightgray
@@:
lodsb
stosw
loop @b
 
}
 
macro show_timer_message
{
;;;;;;;;;;;;;;;;;;;;; show Press any key
;;;;;;;;;;;;;;;;;;;;; show ramk
 
xor ax, ax
mov di, 3360
mov cx, 80*4
rep stosw
 
mov di, 3362
mov ah, color_sym_pink
mov al, 0xDA
stosw
mov al, 0xc4
mov cx, 76
rep stosw
mov al, 0xBF
stosw
add di, 4
mov al, 0xb3
stosw
add di, 152
stosw
add di, 4
stosw
add di, 152
stosw
add di, 4
mov al, 0xc0
stosw
mov al, 0xc4
mov cx, 76
rep stosw
mov al, 0xd9
stosw
;;;;;;;;;;;;;;;;;;;;;;;;ramk is complete show
;show first message
mov si, start_msg
mov cx, start_msg_e-start_msg
mov di, 3526
@@:
lodsb
stosw
loop @b
;;;;;;;;;;;;;;;;;;;; show press Enter to....
add di, 44
mov si, time_msg
mov cx, time_msg_e-time_msg
@@:
lodsb
stosw
loop @b
}
 
 
 
 
 
 
 
 
macro get_frame_buffer
{
mov cx, save_cx ;it's placed size of ini file
les di, dword [file_data]
 
mov si, di ;point frame
mov bx, cx
mov dx, size_show_section
; mov point_to_hframe,di ; внесем значение, так подстраховка не более
 
mov al, byte [es:di]
push word .first_ret_bl_sc
cmp al, ' '
jz .first_bl_sc
jmp get_firs_sym.not_space
.first_bl_sc:
jmp get_firs_sym.first_sp
 
.start_hbl:
call get_firs_sym ;get first symbol on new line
test cx, cx
jz error.correct_exit_bl ;critical error not found default point it's not possible because it's param chacking before
cmp al, '['
jnz .start_hbl
 
mov si, di ;point frame
mov bx, cx
mov dx, size_show_section
jmp .analisist_al
 
 
.start_bl:
call get_firs_sym ;get first symbol on new line
.first_ret_bl_sc: ;первый возврат
test cx, cx
jz error.correct_exit_bl ;critical error not found default point it's not possible because it's param chacking before
.analisist_al:
cmp al, '['
jnz .start_bl
;просматриваем ini файл с начала в поисках секции указаной как default
;поиск фрейма в котором содержиться значение default
.found_sect_bl:
cmp di, point_loader
jz .start_bl
cmp di, point_default
jz .save_point_def
 
dec dx
jnz .start_bl
 
jmp .start_hbl
 
 
.save_point_def:
;итак далее мы должны заполнить frame буфер адресов секций, что бы потом по нему быстро перемещаться не вычисляя снова адреса
mov di, si ;указатель на начало
mov cx, bx
lea si, point_to_hframe
mov dx, size_show_section+1 ;т.к. у нас структура содержит размер между первым и вторым указателем, то нам нужно на 1 адрес больше обсчитать секций.
;переходим на обработку значения указателя
mov al, byte [es:di]
push word .first_ret_mfb
cmp al, ' '
jz .first_bl_mbf
jmp get_firs_sym.not_space
.first_bl_mbf:
jmp get_firs_sym.first_sp
 
.start_mfb:
call get_firs_sym ;get first symbol on new line
.first_ret_mfb: ;первый возврат
jcxz .val_buff_comp ;.end_loader ;found or not found parametrs in section exit in section
cmp al, '['
jnz .start_mfb
 
.found_sect_mfb:
cmp di, point_loader ;if we have section loader
jz .start_mfb
 
mov [si], di
 
sub si, 2
dec dx
jnz .start_mfb
;bufer is full
jmp @f
.val_buff_comp:
push save_cx
pop word [si]
sub si, 2
@@:
 
add si, 4
mov point_to_eframe, si
 
}
 
macro show_act_cursor
{
;отображение курсора по умолчанию
lea si, point_to_hframe
mov di, 962-160
mov ax, point_default
mov cx, size_show_section
.home_show_cur:
mov bx, [si]
add di, 160
cmp bx, ax
jz .show_cursor_activ
sub si, 2
loop .home_show_cur
 
.show_cursor_activ:
; push 0xb800
; pop es
mov point_to_point_def, si
mov ax, (color_sym_red*0x100+0x10)
stosw
add di, 68
inc ax
stosw
}
 
macro clear_timer_msg
{
push 0xb800
pop es
xor ax, ax
if DEBUG
mov ax, 0x0720
end if
;;;;;;;;;;;;;;;;;;;;; show Press any key
mov di, 3360
mov cx, 80*4
rep stosw
 
;show sect
push ini_data_
pop es
call show_bl_sc_sect ;es=0xb800
 
}
 
macro show_descript
;Этот макрос показывает краткое описание, если оно есть у секции в пункте
;Section description
{
local .start_p_sh_d
local .exit
local .rest_value_loop_sh_d
local .end_sh_desc_sec
local .loop_message
local .show_mess_prev_eq
mov di, point_default
push ini_data_
mov si, point_to_point_def
pop es
sub si, 2
mov cx, [si] ;загрузим указатель наследующию секцию
sub cx, di ;вот теперь имеем истиный размер
;di - указатель на дефолтную секцию т.е. выбранную cx - размер области. для просмотра
 
.start_p_sh_d:
call get_firs_sym ;get first symbol on new line
test cx, cx
jz .exit ;нету? ну ладно - следующее значение тогда )
cmp al, 'd'
jnz .start_p_sh_d
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
mov bx, cx
mov ax, di
 
mov si, parse_descript
mov cx, parse_descript_e - parse_descript
repe cmpsb
jnz .rest_value_loop_sh_d ;is not compare
 
sub bx, parse_descript_e - parse_descript;correct cx
add bx, cx
mov cx, bx
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; разбор аля ' = '
mov ax, 0x3d20 ;cut al=' ' ah='='
repe scasb
jcxz .rest_value_loop_sh_d ;not found param timeout
cmp ah, byte [es:di-1] ;find '='
jnz .rest_value_loop_sh_d
repe scasb ;cut ' '
inc cx
dec di
;;;;;;;;;;;;;;;;;;;;di указывает на строчку, которую нам нужно выводить.
;строчка будет выводиться блоками по 37 символов.
;настроим куда будем выводить т.е. начало
;es:di - указывают на строчку из которой мы берем символ, ds:si куда будем выводить
push di
pop si
 
push es
pop ds
 
push 0xb800
pop es
mov di, 1040
mov bx, 18
mov find_sec_di, di
mov save_cx_d, bx
;;;;;;;;;;;;;;;;;;;;;;;;;;
;clean string
 
push di
xor ax, ax
 
@@:
mov cx, 38
push di
rep stosw
pop di
 
cmp save_descript_size, bx
jz @f
 
 
add di, 160
dec bx
jnz @b
 
@@:
pop di
;enter in mess
.show_mess_prev_eq:
lodsb
mov ah, color_sym_lettuce;color_sym_turquoise
; sub di,2
cmp al, '"'
jz .loop_message
cmp al, "'"
jnz .end_sh_desc_sec
 
.loop_message:
mov cx, 38
@@:
lodsb
cmp al, '"'
jz .end_sh_desc_sec
cmp al, "'"
jz .end_sh_desc_sec
stosw
loop @b
add find_sec_di, 160
mov di, find_sec_di
dec save_cx_d
cmp save_cx_d, 0
jnz .loop_message
 
.end_sh_desc_sec:
push save_cx_d
pop save_descript_size
 
push cs
pop ds
jmp .exit
 
 
.rest_value_loop_sh_d:
mov di, ax
mov cx, bx
jmp .start_p_sh_d
 
.exit:
}
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/debug_msg.inc
0,0 → 1,77
; Copyright (c) 2009, <Lrz>
; 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.
;*****************************************************************************
 
;Тут определены все сообщения, которые нужны в процессе отладки, и совсем не нужны в рабочей копии программы.
If DEBUG
cseg_msg db ' - Adress of code segment',0
stack_msg db 'Set stack & segments is have completed',0
show_string db 'Have loaded size:'
show_decode db ' ',0
show_db1 db ' -Message debug1',0
show_db2 db ' -Message debug2',0
 
 
lm_l_found db '[loader] is found',0
lm_lf_timeout db 'timeout is found',0
lm_lf_default db 'name default is found and end parsing section',0
lm_lf_section db 'found section [',0
lm_lf_default_f db 'found default parametr',0
lm_l_end db 'section [loader] is end',0
show_all_sect db 'SHOW ALL Sections',0
no_show_only_w db 'Not show sections - only work on default sect',0
_not_found db '[ not found',0
_found_1 db '[] found',0
_found_2 db '[ found',0
say_hello db 'Hello $)',0
ramdiskFS_st db 'Start use_RamdiskFS macros',0
free_memory_msg db ' -Kb availability system free memory',0
RamdiskSize_msg db ' -Kb equal RamdiskSize',0
RamdiskSector_msg db ' -byts RamdiskSector',0
RamdiskCluster_msg db ' -RamdiskCluster',0
RamdiskFile_msg db ' -size RamdiskFile',0
fat_create_msg db ' -first create fat table, point to next block',0
BPB_msg db ' -in byte, why we get data from move BPB struct',0
firstDataSect_msg db ' -first data sector, offset to data in sectors',0
size_root_dir_msg db ' -size root dir in sectrors',0
DataClasters_msg db ' -size data in Clasters',0
first_entry_in_fat db ' -data segment in FIRST entry FAT',0
check_root_fat_ db ' : --------------',0
check_name_fat_msg_y db 'Name is present that is BAD',0
check_name_fat_msg_n db 'Name is not present that is GOOD',0
name_of_seg_get_64 db ' -name of seg where we get 64 Kb of data',0
convertion_file_name_msg_y db '->Destination name of file is GOOD',0
convertion_file_name_msg_n db '->Destination name of file is BAD',0
alarm_msg db '%%%%%%%% WARNING: MISS THE FILE %%%%%%%%%%%',0
start_making_FAT12_msg db '>>>>>> Begin make a RAMDISK and FS after 1 Mb <<<<<<<',0
make_fat12_RFS_msg db '-Make FAT12 Ram FS',0
get_type_FS_msg db '-End make RamDisk',0
seg_where_get_data db ' - Segment where we get data for move up file',0
return_code_af_move db ' -return code after 0x87 int 0x15, move block',0
return_code_af_fat_m db ' -return code after 0x87 int 0x15, move fat struc',0
 
 
 
end if
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/loader.asm
0,0 → 1,317
; Copyright (c) 2008-2009, <Lrz>
; 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 nickname <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.
;*****************************************************************************
 
;start of the project 13.02.2008 year.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Secondary Loader copyright Alexey Teplov nickname <Lrz>
;if you need log preproc
;/////////////
;include 'listing.inc'
;enable listing
;////////////
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;start of code: ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use16
org 0x0
jmp start
include 'sl_equ.inc' ; в файле размещены все equ предопределения
include 'boot_st.inc'
include 'debug_msg.inc' ;here is message from debug
include 'parse_dat.inc'
include 'sl_proc.inc'
include 'parse.inc'
include 'parse_loader.inc'
include 'parse_any.inc'
include 'parse_def_sect.inc'
include 'parse_err.inc'
 
file_data dw 0x0,ini_data_ ;формат: смещение: сегмент т.к. используется les
size_data dw 16 ;16 блоков по 4 кб т.е предел до 64 кб
name_ini_f db 'kord/startos.ini',0
 
;////////////
loader_callback dd ?
load_drive dw ?
load_ft dw ?
;Start code
 
start:
; Save far pointer to callback procedure, ds:si is point
mov word [cs:loader_callback], si
mov word [cs:loader_callback+2], ds
; Save type of drive
mov word [cs:load_drive], ax
; Save type of FT
mov word [cs:load_ft], bx
; set up stack
mov ax, cs
mov ss, ax
xor sp, sp
; set up segment registers
mov ds, ax
mov es, ax
; just to be sure: force DF=0, IF=1
cld
sti
 
; set videomode
mov ax, 3
int 0x10
 
mov si, version
call printplain
mov al, '#'
mov cx, 80
;input cx=size al=char будет вывден символ сколько раз указано в cx
@@:
call putchar
loop @b
 
if DEBUG
pushad
mov ax, cs
shl eax, 4 ; в десятичной системе адрес сегмента
mov cx, 0xa
mov di, cseg_msg
call decode
;***************
mov si, cseg_msg
call printplain
popad
end if
 
 
if DEBUG
mov si, stack_msg
call printplain
end if
 
; Require 586 or higher processor (cpuid and rdtsc,rdmsr/wrmsr commands)
; install int 6 (#UD) handler
xor bx, bx
mov ds, bx
push word [bx+6*4+2]
push word [bx+6*4]
mov word [bx+6*4], ud16
mov word [bx+6*4+2], cs
; issue CPUID command
xor eax, eax ; N.B.: will cause #UD before 386
cpuid ; N.B.: will cause #UD before later 486s
test eax, eax
jz cpubad
; get processor features
xor eax, eax
inc ax
cpuid
test dl, 10h ; CPUID[1].edx[4] - TSC support
jz cpubad
test dl, 20h ; CPUID[1].edx[5] - MSR support
jnz cpugood
 
ud16: ; #UD handler, called if processor did not recognize some commands
cpubad:
; restore int 6 (#UD) handler
pop word [6*4]
pop word [6*4+2]
; say error
push cs
pop ds
mov si, badprocessor
sayerr:
call printplain
jmp $
 
cpugood:
; restore int 6 (#UD) handler
pop dword [6*4]
push cs
pop ds
 
; set up esp
movzx esp, sp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; init memory
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
 
 
; Load startos.ini
mov cx, loop_read_startos_file ;кол-во попыток чтения файла конфигурации startos.ini
align 4
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Load startos.ini ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
load_startos_file:
 
xor ax, ax
mov di, file_data
inc ax ;function 1 - read file
push cx
call far dword [loader_callback]
pop cx
push cs
push cs
pop ds
pop es
 
test bx, bx
jz check_conf_file
dec cx
jnz load_startos_file
 
;SET DEFAULT Not use ini file
error_ini:
mov si, error_ini_f1 ;Error: cannot load ini file, buffer is full
dec bx
jz err_show_ini
mov si, error_ini_f2 ;Error: ini file not found
dec bx
jz err_show_ini
mov si, error_ini_f3 ;Error: cannot read ini file
dec bx
jz err_show_ini
 
mov si, error_ini_nf ;Error: unrecognized error when loading ini file
err_show_ini:
call printplain
mov si, error_ini_common
call printplain
; wait for keypress
xor ax, ax
int 16h
 
ini_loaded:
 
jmp $
 
align 4
check_conf_file:
;Check config file in current dir
push ax ;save size file
if DEBUG
mov cx, 0x0a
mov di, show_decode
call decode
;Show size
mov si, show_string
call printplain
end if
 
 
;Show message
mov si, load_ini
call printplain
 
pop cx ;restore size file
use_parse ;parsing startos.ini
;
jmp ini_loaded
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;DATA
;;;;;;;;;;;;;;;;;;;;;;;;;;;
; table for move to extended memory (int 15h, ah=87h)
align 4
table_15_87:
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
 
db 0xff,0xff
db 0x0,0x10
db 0x00,0x93,0x0,0x0
 
db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0
 
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
 
fat12_buffer:
.BS_jmpBoot db 0x90,0x90,0x90 ;3 байта NOP инструкция - ничего не делать
.BS_OEMName db 'K SyS 64' ;8 байт
.BPB_BytsPerSec dw 512 ;кол-во байтов в секторе может быть любое 512 1024 2048 4096 2 байта
.BPB_SecPerClus db 0x1 ;кол-во секторов в кластере
.BPB_RsvdSecCnt dw 0x1 ;для FAt12/16 только 1, для FAT32 обычно 32
.BPB_NumFATs db 0x1 ;кол-во фат таблиц, на тот случай если будет сброс на дискету образа рам диска
.BPB_RootEntCnt dw 512 ;для мак совместимости с fat16
.BPB_TotSec16 dw 0x0 ;кл-во секторов
.BPB_Media db 0xF0
.BPB_FATSz16 dw 0x0
.BPB_SecPerTrk dw 0x0 ;содержит геометрию диска для RAMFS на как бы без разницы, пока пустое поле, позже внести реальные значения.
.BPB_NumHeads dw 0x0
.BPB_HiddSec dd 0x0 ;кол-во скрытых секторов
.BPB_TotSec32 dd 0x0
.BS_DrvNum db 'R' ;от слова RAM
.BS_Reserved1 db 0x0
.BS_BootSig db 0x29
.BS_VolID db 'RFKS'
.BS_VolLab db 'RAM DISK FS' ;11 символов
.BS_FilSysType db 'FAT12 ' ;8 символов
;62 байта структура fat12.
db (512-($-fat12_buffer))dup(0x90)
 
 
 
;структура для дирректории fat
struc FAT_32_entry ;Byte Directory Entry Structure
{
.DIR_Name rb 11
.DIR_Attr db ?
.DIR_NTRes db ?
.DIR_CrtTimeTenth db ?
.DIR_CrtTime dw ?
.DIR_CrtDate dw ?
.DIR_LstAccDate dw ?
.DIR_FstClusHI dw ?
.DIR_WrtTime dw ?
.DIR_WrtDate dw ?
.DIR_FstClusLO dw ?
.DIR_FileSize dd ?
 
 
}
;Тут будут распологатсья данные, которые затруднительно распологать в стековой области....
;;;
;timer
shot_name_fat rb 11 ;временный буфер для fat12, в нем храняться имена файлов приведенные к правилам FAT /* вдальнейшем перенести в стэк
 
if DEBUG
rb 1 ;нужен для отладки и вывода имени файла после преобразования
dest_name_fat db 24 dup('_');12
db 0x0
end if
 
value_timeout rw 1 ;value to timeout
old_timer rd 1 ;старое значение вектора таймера
start_timer rd 1 ;значение таймера
timer_ rd 1 ;новое значение вектора таймера т.е. SL
start_stack rw 1 ;save stack
save_bp_from_timer rw 1 ;save bp from timer
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/parse.inc
0,0 → 1,118
; Copyright (c) 2009, <Lrz>
; 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 nickname <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.
;*****************************************************************************
 
; Модуль парсинга - это стандартный компонент, встраиваемый во вторичный загрузчик.
; Данный модуль позволяет стандартно произвести разбор ini файла
; (и с использованием полученных данных ОС будет загружаться дальше).
; В начале найдем открывающий "[" - это будет указывать на начало
; секции. Поддерживается 1 секция это [loader], остальные секции могут иметь
; любые имена, но они должны быть заключены в в скобки []
macro use_parse
{
;input cx=size of ini file
parse_start:
;es:di as 2000:0000 new segment
;установим указатель на загруженный блок
enter 256, 0 ;set 16 byte for current task in stack
;we are is not use bp because bp is pointer on array 16 byte
mov word [save_bp_from_timer], bp ;save point to own data array
mov save_cx, cx ;it's placed size of ini file
les di, dword [file_data]
;обнулим все переменные выделенные из стека
;init flag
xor ax, ax
mov status_flag, ax
;set data size
mov info_real_mode_size, ini_data_ +0x1000 ;изменим значение занятости памяти
 
;поиск начала блока.
;///////////check [loader]
cld
 
mov ret_on_ch, .start ;set return
mov al, byte [es:di]
push word .first_ret
cmp al, ' '
jz .first_sp_1
jmp get_firs_sym.not_space
.first_sp_1:
jmp get_firs_sym.first_sp
 
.start:
call get_firs_sym ;get first symbol on new line
.first_ret: ;первый возврат
; jcxz .end_file ;.end_loader ;found or not found parametrs in section exit in section
test cx, cx
jz error.not_loader
cmp al, '['
jz .parse_loader
jmp .start
;////// проверка на наличее секции loader
use_parse_loader
;pause
if DEBUG
xor ax, ax
int 16h
end if
;////// вывод графического экрана, выбор, секции под дефолту
use_any_sec
;парсинг выбраной или дефолтной секции т.е. разбор параметров выполнение сценария
use_parse_def_sect
 
;//////////////////
;/end parse block
;//////////////////
;.end_bl:
; mov cx,bx
;
; jmp .start
 
.exit:
 
; mov si,parse_ini_end
; call printplain
;
;if DEBUG
; pusha
; mov ax,cx
; mov cx,0x0a
; mov di,show_db1_dec
; mov dword[ds:di],' '
; call decode
;Show size
; mov si,show_db1
; call printplain
;
; popa
;end if
jmp $
 
;///////////////////procedure //////////
;input es:di - is pointer to date
;cx - counter
;return: cx - status if =0 - end of date else es:di point to first symbol on new line
 
}
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/parse_dat.inc
0,0 → 1,56
; Copyright (c) 2009, <Lrz>
; 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 nickname <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.
;*****************************************************************************
 
;Тут представленны теги, для сравнения
parse_loader db '[loader]'
parse_loader_e:
parse_l_timeout db 'timeout'
parse_l_timeout_e:
parse_l_default db 'default'
parse_l_default_e:
parse_name db 'ame'
parse_name_e:
parse_descript db 'descript'
parse_descript_e:
 
parse_LoaderModule db 'LoaderModule'
parse_LoaderModule_e:
parse_RamdiskSize db 'RamdiskSize'
parse_RamdiskSize_e:
parse_RamdiskFS db 'RamdiskFS'
parse_RamdiskFS_e:
parse_RamdiskSector db 'RamdiskSector'
parse_RamdiskSector_e:
parse_RamdiskCluster db 'RamdiskCluster'
parse_RamdiskCluster_e:
parse_RFS_FAT db 'FAT'
parse_RFS_FAT_e:
parse_RFS_KRFS db 'KRFS'
parse_RFS_KRFS_e:
parse_Loader_Image db 'LoaderImage'
parse_Loader_Image_e:
parse_RamdiskFile db 'RamdiskFile'
parse_RamdiskFile_e:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/parse_def_sect.inc
0,0 → 1,2121
; Copyright (c) 2009, <Lrz>
; 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 nickname <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.
;*****************************************************************************
 
; в этой секции идет разбор параметров указатель на секцию храниться в point_default
;типы ошибок при обработке макроса
;Макрос RamdiskFS
;/определение флагов в записи корневой директории
ATTR_READ_ONLY equ 0x01
ATTR_HIDDEN equ 0x02
ATTR_SYSTEM equ 0x04
ATTR_VOLUME_ID equ 0x08
ATTR_DIRECTORY equ 0x10
ATTR_ARCHIVE equ 0x20
 
 
 
show_error_1 equ 0x1 ;кончились данные - не запланированный конец секции
show_error_2 equ 0x2 ;нет завершающего символа в размере рам диска.
show_error_3 equ 0x4 ; рам диск будет иметь размер =64 кб.
show_error_4 equ 0x8 ;
 
macro use_parse_def_sect
{
mov di, point_default
push ini_data_
pop es
mov si, point_to_point_def
sub si, 2
mov cx, [si] ;загрузим указатель наследующию секцию
 
xor ax, ax ;обнулим аx для очистки флагов
 
sub cx, di ;вот теперь имеем истиный размер
mov save_cx_d, cx ;сохраним значение cx своей переменной
;обнулим переменную флагов, это необходимо, для того, что бы избежать обработку повторяющихся значений
 
mov status_flag, ax
;;;;
;ВХод в обработку парсинга значений секций. es:di - указатель на начало секции cx размер секции доступной для парсинга
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;соглашение не разрушаем bp, es, cs, sp
;use_Loader_Image ;загрузить образ выше 1 мб
use_RamdiskFS
;проверяется самый последний.
use_LoaderModule ;особенность - передает управление на загруженный модуль.
}
 
macro use_LoaderModule
;как вариант сейчас используется модель, при загрузке модуля на него передается управление, решение временое
;управление будет передаваться только после обработки всей секции
{
local .found_end_str
 
mov di, point_default ;restore value
mov cx, save_cx_d
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
.start_p_LM:
call get_firs_sym ;get first symbol on new line
test cx, cx
jz ._afterLoaderModule ;нету? ну ладно - следующее значение тогда )
cmp al, 'L'
jnz .start_p_LM
;проверка на значение LoaderModule
; parse_LoaderModule
mov bx, cx
mov ax, di
 
mov si, parse_LoaderModule
mov cx, parse_LoaderModule_e - parse_LoaderModule
repe cmpsb
jnz .rest_value_loop_LM ;is not compare
 
sub bx, parse_LoaderModule_e - parse_LoaderModule;correct cx
add bx, cx
mov cx, bx
 
test status_flag, flag_found_LM ;оценка флагов
jz .correct_is_not_set_LM
 
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
; call printplain
; jmp .get_next_str
 
.correct_is_not_set_LM:
mov ax, 0x3d20 ;cut al=' ' ah='='
repe scasb
jcxz .rest_value_loop_LM ;not found param timeout
cmp ah, byte [es:di-1] ;find '='
jnz .rest_value_loop_LM
repe scasb ;cut ' '
inc cx
dec di
;di указывает на начало блока информации, в cx длинна до конца секции.
;после загрузки заноситься значение занятой памяти.
;для того что бы загрузить модуль, воспользуемся callback сервисом
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader
;мы ее модифицируем до такого состояния dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем
;сохранили певые 2 word
push dword [es:di-6]
lea si, [di-6]
 
push word [es:di-2]
xor ax, ax
mov word [es:di-6], ax ;вносим нужные значения
;info_real_mode_size размер и указатель на область в которую можно загрузиться
mov ax, info_real_mode_size ;0x3000 ;следующий сегмент за данными
 
 
mov word [es:di-4], ax
mov word [es:di-2], 16 ;кол-во блоков по 4 кб =64 кб т.е. больше не считаем
;;;;;; поиск конца строчки
@@:
mov al, byte [es:di]
cmp al, ' '
jz .found_end_str
cmp al, 0xa
jz .found_end_str
cmp al, 0xd
jz .found_end_str
inc di
dec cx
jnz @b
;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки
.found_end_str:
 
push word [es:di]
xor ax, ax
mov word [es:di], ax
; xor ax,ax ; function 1 - read file
mov di, si ;file_data
inc ax
push si
push es
 
push es
pop ds
push cs
pop es
 
call far dword [es:loader_callback]
 
push cs
pop ds
 
pop es
pop si
 
test bx, bx
jnz .error_LM
 
 
jmp far dword [es:si]
 
 
.error_LM:
call error.LoaderModule
.rest_value_loop_LM:
mov di, ax
mov cx, bx
jmp .start_p_LM
 
._afterLoaderModule:
}
 
macro use_RamdiskFS
; формирование рам диска, + обработка всего связанного.
{
if DEBUG
local ._not_memory_in_sys
;//////// clear window
mov ax, 3
int 0x10
;\\\\\\\\\ clear window is end
mov si, ramdiskFS_st
call printplain
end if
; обнулим регистр состояния ошибок
xor ax, ax
mov show_errors_sect, ax
use_free_memory ; узнаем какого объема у нас доступна память. значение возаращается в ax
;узнаем сколько у нас есть памяти и сможем ли мы сформировать нужного размера рам диск.
use_RamdiskSize ;значение возвращается в bx
cmp free_ad_memory, bx ; размерность в кб.
jbe ._not_memory_in_sys
movzx eax, bx
shl eax, 10 ;*1024 = get size in byte
mov save_ramdisksize, eax ; сорханим размер в byte
 
get_type_FS ;получим тип файловой системы + создадим ее
 
._not_memory_in_sys:
if DEBUG
;pause
xor ax, ax
int 0x16
end if
}
macro use_RamdiskSize
{
local .start_p_RS
local .correct_is_not_set_RS
local .CS
local .correct_val_RS
local .correct_size_RS
local .rest_value_loop_RS
local .end_get_RS_ERROR_1
local .end_get_RS_ERROR_2
local ._end_parse_RS
;обрабатывается размер формируемого рам диска
;загрузим начало секции, т.к. будем просматривать с начала и всю секцию
mov di, point_default ;restore value
mov cx, save_cx_d
.start_p_RS:
call get_firs_sym ;get first symbol on new line
test cx, cx
jz ._end_parse_RS ;нету? ну ладно - следующее значение тогда )
cmp al, 'R'
jnz .start_p_RS
;проверка на значения RamdiskSize
; parse_RamdiskSize
mov bx, cx
mov ax, di
 
mov si, parse_RamdiskSize
mov cx, parse_RamdiskSize_e - parse_RamdiskSize
repe cmpsb
jnz .rest_value_loop_RS ;is not compare
 
sub bx, parse_RamdiskSize_e - parse_RamdiskSize;correct cx
add bx, cx
mov cx, bx
 
test status_flag, flag_found_RS ;оценка флагов
jz .correct_is_not_set_RS
 
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
; call printplain
; jmp .get_next_str
 
.correct_is_not_set_RS:
mov ax, 0x3d20 ;cut al=' ' ah='='
repe scasb
jcxz .end_get_RS_ERROR_1 ;not found param
cmp ah, byte [es:di-1] ;find '='
jnz .start_p_RS ; перейдем на начало и попробуем найти еще секцию
repe scasb ;cut ' '
inc cx
dec di
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Тут нужно преобразовывать строчку в цифровое значение.
;;;;;;;;;;;;;;;;;;;;;;;;;;
xor bx, bx
mov cx, 5
@@:
mov al, byte [es:di]
cmp al, '0'
jb .CS
cmp al, '9'
jbe .correct_val_RS
.CS:
cmp al, 'K'
jz .correct_size_RS
jmp .end_get_RS_ERROR_2
.correct_val_RS:
imul bx, 10
xor al, 0x30
add bl, al
inc di
loop @b
 
.correct_size_RS:
;возможен 1 вариант, когда размер задан в K киллобайтах
;внутренный формат данных это кол-во запрощеной памяти в кб.
test bx, bx
jnz @f ;если значение отлично от 0
;;;;;сообщение об ошибке, размер "найденого" блока =0 минимально мы должны
;установить 64 кб размер рам диска.
or show_errors_sect, show_error_3
mov bx, 64
@@:
jmp ._end_parse_RS
 
 
.rest_value_loop_RS:
mov di, ax
mov cx, bx
jmp .start_p_RS
.end_get_RS_ERROR_1:
;сообщение об ошибке - данный участок кода не был корректно обработан :(
or show_errors_sect, show_error_1
jmp ._end_parse_RS
.end_get_RS_ERROR_2:
or show_errors_sect, show_error_2
 
._end_parse_RS:
if DEBUG
pusha
movzx eax, bx
mov cx, 0x0a
mov di, RamdiskSize_msg
mov dword[ds:di], ' '
mov word [ds:di+4], ' '
call decode
;Show size
mov si, RamdiskSize_msg
call printplain
 
popa
end if
 
}
 
macro use_free_memory
{
local _support_function_use_free_memory
;макрос для получения общего числа доступной памяти в кб, для формирования рам диска за пределами 1 мб.
;используется 0х88 функция 0х15 прерывания
; если поддерживается функция, то в ax значение в кб, если нет, то в ax=0
mov ah, 0x88 ;ah,0x88
int 0x15
jnc ._support_function_use_free_memory
xor ax, ax
;возвращает в ax число в кб
._support_function_use_free_memory:
mov free_ad_memory, ax ; если не поддерживается биосом, то в ax=0
if DEBUG
pushad
movzx eax, ax
mov cx, 0x0a
mov di, free_memory_msg
mov dword[ds:di], ' '
mov word [ds:di+4], ' '
call decode
;Show size
mov si, free_memory_msg
call printplain
 
popad
end if
 
 
 
 
}
macro show_ERRORS
{
 
}
 
macro get_type_FS ;получить и создать образ для заданной RFS.
{
mov di, point_default ;restore value
mov cx, save_cx_d
.start_g_tpe_RFS:
call get_firs_sym ;get first symbol on new line
test cx, cx
jz ._end_parse_FRS ;._end_get_type_RFS ;нету? ну ладно - следующее значение тогда )
cmp al, 'R'
jnz .start_g_tpe_RFS
;проверка на значения RamdiskSize
; parse_RamdiskSize
mov bx, cx
mov ax, di
 
mov si, parse_RamdiskFS
mov cx, parse_RamdiskFS_e - parse_RamdiskFS
repe cmpsb
jnz .start_g_tpe_RFS_rest_v ;is not compare
 
sub bx, parse_RamdiskFS_e - parse_RamdiskFS;correct cx
add bx, cx
mov cx, bx
 
test status_flag, flag_found_GTRFMS ;оценка флагов
jz .correct_is_not_set_FRS
 
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
; call printplain
; jmp .get_next_str
 
.correct_is_not_set_FRS:
mov ax, 0x3d20 ;cut al=' ' ah='='
repe scasb
test cx, cx
jz .end_get_FRS_ERROR_1 ;not found param
cmp ah, byte [es:di-1] ;find '='
jnz .start_g_tpe_RFS ; перейдем на начало и попробуем найти еще секцию
repe scasb ;cut ' '
inc cx
dec di
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Тут нужно преобразовывать строчку в цифровое значение.
;;;;;;;;;;;;;;;;;;;;;;;;;;
mov bx, cx
mov ax, di
 
mov si, parse_RFS_FAT
mov cx, parse_RFS_FAT_e - parse_RFS_FAT
repe cmpsb
jnz .krfs_cmp ;is not compare
 
make_FAT_RamFS ;сделать
 
if DEBUG
pusha
mov si, make_fat12_RFS_msg
call printplain
popa
end if
jmp ._end_parse_FRS
 
.krfs_cmp:
mov cx, bx
mov di, ax
 
mov si, parse_RFS_KRFS
mov cx, parse_RFS_KRFS_e - parse_RFS_KRFS
repe cmpsb
; jnz @f ;is not compare
 
jmp ._end_parse_FRS
 
 
.start_g_tpe_RFS_rest_v:
mov cx, bx
mov di, ax
jmp .start_g_tpe_RFS
.end_get_FRS_ERROR_1:
;сообщение об ошибке - данный участок кода не был корректно обработан :(
or show_errors_sect, show_error_1
jmp ._end_parse_FRS
.end_get_FRS_ERROR_2:
or show_errors_sect, show_error_2
 
._end_parse_FRS:
if DEBUG
pusha
mov si, get_type_FS_msg
call printplain
popa
end if
 
 
 
}
macro make_FAT_RamFS
{
local .RS1
local .fat12
local .fat16
; мы должны сформировать в начальный образ Ram FS, а потом записать его за область выше 1 мб..
;для случая с FAT12
; mov di,fat12_buffer ;ds должен быть = cs
;es:di - указывают на начало блока для формирования рам фс.
use_RamdiskSector ;возращаемое значение в ax размер сектора в байтах
cmp ax, 4096;по спецификации значение должно быть в пределах от 1 до 4096
ja .RS1
test ax, ax
jnz @f ;ошибка если сюда прыгнули все таки ...
 
.RS1:
mov word [fat12_buffer.BPB_BytsPerSec], 512
;;;;;;;;;;скажем что по дефолту будем юзать значение...
@@:
mov word [fat12_buffer.BPB_BytsPerSec], ax;тут все ок
 
;BPB_SecPerClus кол-во секторов в кластере
use_RamdiskCluster ;возращаемое значение в al
cmp al, 128
ja @f
; test al,0x1 ;проверка на кратность )
; jnz @f
 
mov byte [fat12_buffer.BPB_SecPerClus], al
 
;incorrect value will be set dafault
 
;ниже некорректное значение в т.к. размер кратен 2 и в диапазоне от 1 до 128 включительно
; мы должны ругнуться на это
;@@: ;mov byte [fat12_buffer.BPB_SecPerClus],1
 
;;;;; определеим какая у нас будет использоваться FAT
;по условию, fat12<4085<=fat16<65525<=fat32
; fat12_buffer.BPB_BytsPerSec*fat12_buffer.BPB_SecPerClus = кол-во секторов
movzx eax, word [fat12_buffer.BPB_BytsPerSec]
movzx ebx, byte [fat12_buffer.BPB_SecPerClus]
 
imul ebx, eax;тут размерность сектора
mov eax, save_ramdisksize ;размер запрошенного рам диска в байтах
cdq
idiv ebx
;;;;;;;; сейчас частное в eax, а остаток в edx
;получим кол-во секторов, и можем уже определить тип FAT которую нужно делать.
cmp eax, 4085
jb .fat12
cmp eax, 65525
jb .fat16
;;;;;;;;;;;;;;;;;;;;;;;; тут fat32
mov set_ramfs, 32 ;установим тип файловой системы
mov word [fat12_buffer.BPB_RsvdSecCnt], 32
xor eax, eax
mov word [fat12_buffer.BPB_RootEntCnt], ax
mov word [fat12_buffer.BPB_TotSec16], ax
mov dword [fat12_buffer.BPB_TotSec32], eax
 
 
.fat16: ;fat16
;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000).
jmp $
mov set_ramfs, 16 ;установим тип файловой системы
movzx ebx, byte [fat12_buffer.BPB_SecPerClus]
imul eax, ebx
 
cmp eax, 0x10000
jae @f
mov word [fat12_buffer.BPB_TotSec16], ax
mov dword [fat12_buffer.BPB_TotSec32], 0
@@:
;количество секторов занимаемое одной копией фат
; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Для FAT12/FAT16 это количество секторов одной FAT. ??
;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число
;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно
;быть 0. Пока константа, нужно будет позже доделать.
mov eax, root_dir_entry_count
mov word [fat12_buffer.BPB_RootEntCnt], ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб
;;;;;;;
;Для FAT16 это количество секторов одной FAT. Для FAT32 это значение
;равно 0, а количество секторов одной FAT содержится в BPB_FATSz32.
;RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec - 1)) / BPB_BytsPerSec;
 
;TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors);
;TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
;If(FATType == FAT32)
; TmpVal2 = TmpVal2 / 2;
;FATSz = (TMPVal1 + (TmpVal2 - 1)) / TmpVal2;
;If(FATType == FAT32) {
; BPB_FATSz16 = 0;
; BPB_FATSz32 = FATSz;
;} else {
; BPB_FATSz16 = LOWORD(FATSz);
; /* there is no BPB_FATSz32 in a FAT16 BPB */
;}
;=====================================
;RootDirSectors
movzx ebx, word [fat12_buffer.BPB_BytsPerSec]
imul eax, 32
add eax, ebx
dec eax
 
cdq
idiv ebx
;;;;;;;; сейчас частное в eax, а остаток в edx для дискеты 1.44 у нас должно быть значение =14
;BPB_ResvdSecCnt + RootDirSectors
movzx ebx, word [fat12_buffer.BPB_RsvdSecCnt]
add ebx, eax
;DskSize у нас это значение уже получено и доступно
movzx eax, word [fat12_buffer.BPB_TotSec16] ;должен быть в секторах
sub eax, ebx
 
 
;TmpVal1=eax
shl edi, 8 ;=edi*256
movzx ecx, byte [fat12_buffer.BPB_NumFATs]
add edi, ecx
;TmpVal2=edi
add eax, edi
dec eax
cdq
idiv edi
;FATSz = сейчас частное в eax, а остаток в edx
mov word [fat12_buffer.BPB_FATSz16], ax
 
 
 
 
 
 
 
 
.fat12: ;fat12
if DEBUG
; выведем в отладке, что собираемся делать образ диска c FS=fat12
pushad
mov si, start_making_FAT12_msg
call printplain
popad
end if
 
 
 
;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000).
mov set_ramfs, 12 ;установим тип файловой системы
movzx ebx, byte [fat12_buffer.BPB_SecPerClus]
imul eax, ebx
 
cmp eax, 0x10000
jae @f
mov word [fat12_buffer.BPB_TotSec16], ax
mov dword [fat12_buffer.BPB_TotSec32], 0
@@:
;количество секторов занимаемое одной копией фат
; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Для FAT12/FAT16 это количество секторов одной FAT. ??
;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число
;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно
;быть 0. Пока константа, нужно будет позже доделать.
mov eax, root_dir_entry_count
mov word [fat12_buffer.BPB_RootEntCnt], ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб
;;;;;;;
;DskSize(в секторах)*12 (размерность файловой системы, т.е предположим сколько битов потребуется для адресации этого объема) /8 (что получить размер в байтах)
;полученное число округляем в большую сторону кратное сектору т.е. 512 байт Такой подход не универсален, но пока пойдет
;вообще у мелкософт это все считается ручками, но мы будем юзать только под коос рам диск с фат12
movzx eax, word [fat12_buffer.BPB_TotSec16]
imul eax, 12
shr eax, 3 ;делим на 8 но т.е. нам нужно делить еще и на 512 или более в зависимости от размеров кластера
movzx ebx, word [fat12_buffer.BPB_BytsPerSec] ;размер сектора
cdq
idiv ebx ;разделим на размер кластера
;сейчас у нас в eax значение его нужно округлить в большую сторону кратному 512 байтам
;применим следующее очистим and и добавим 512 байт. таким образом выравним на 512 байт
;но т.к. все равно делить нижний код нам не нужен
; and eax,0xfff200
; add eax,0x200 ;добавим 512 байт для 1.44 дискеты идеально подходит ))
 
inc ax
;по идее должно на каждую фат таблицу
;резервироваться 9 секторов т.е. получается 2*9=18+1 =19 секторов т.е. рут дир находиться на с 20 сетора т.е. с адреса 0х2600
;сейчас нужно вычислить сколько будет секторов занимать фат ) нужно разделить на 512
;FATSz = сейчас частное в eax
mov word [fat12_buffer.BPB_FATSz16], ax
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
get_firstDataSector ;получить смещение до данных
;создадим певую запись в фат по определенному адресу.
first_create_fat_table
;закиним BPB файловой системы за 1 мб.
use_BPB_RAM
;
;копирование файла.
use_RamdiskFile
 
;;;; вычисляем указатель на корневую дир FirstRootDirSecNum = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16);
; movzx ebx, [fat12_buffer.BPB_NumFATs]
; movzx eax,ax
; imul eax,ebx
;eax=(BPB_NumFATs * BPB_FATSz16)
; inc eax
; BPB_ResvdSecCnt значение только 1 для fat12/16
;в eax указатель на root dir. для дискеты fat12 должно получиться при кол-во копий fat 1 = 1+ (1*1) =2 или 3
 
if DEBUG
pusha
; mov ax,point_default
; mov ax,cx
mov cx, 0x0a
mov di, show_db1
; mov dword[ds:di],' '
; mov word [ds:di+4],' '
call decode
;Show size
mov si, show_db1
call printplain
;
; xor ax,ax
; int 0x16
popa
end if
 
 
 
 
 
 
 
}
 
macro use_RamdiskSector
{
;для некоторых FS будет игнорироваться
mov di, point_default ;restore value
mov cx, save_cx_d
 
.start_RamdiskSector:
call get_firs_sym ;get first symbol on new line
test cx, cx
jz .end_RamdiskSector ;нету? ну ладно - следующее значение тогда )
 
cmp al, 'R'
jnz .start_RamdiskSector
;проверка на значения RamdiskSize
; parse_RamdiskSize
 
mov bx, cx
mov ax, di
 
mov si, parse_RamdiskSector
mov cx, parse_RamdiskSector_e - parse_RamdiskSector
repe cmpsb
jnz .RamdiskSector_rest_val ;is not compare
 
sub bx, parse_RamdiskSector_e - parse_RamdiskSector;correct cx
add bx, cx
mov cx, bx
 
test status_flag, flag_found_RamdiskSector ;оценка флагов
jz .correct_is_not_set_RamdiskSector
 
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
; call printplain
; jmp .get_next_str
 
.correct_is_not_set_RamdiskSector:
mov ax, 0x3d20 ;cut al=' ' ah='='
repe scasb
jcxz .end_get_RamS_ERROR_1 ;not found param
cmp ah, byte [es:di-1] ;find '='
jnz .start_RamdiskSector ; перейдем на начало и попробуем найти еще секцию
repe scasb ;cut ' '
inc cx
dec di
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
xor bx, bx
mov cx, 4
@@:
movzx ax, byte [es:di]
cmp al, '0'
jb .end_RamdiskSector
cmp al, '9'
ja .end_RamdiskSector
;;;;;;;;;;;;;;;;;;;
 
imul bx, 10
xor al, 0x30
add bx, ax
 
inc di
 
loop @b
jmp .end_RamdiskSector
 
 
.RamdiskSector_rest_val:
mov cx, bx
mov di, ax
jmp .start_RamdiskSector
.end_get_RamS_ERROR_1:
 
.end_RamdiskSector:
mov ax, bx
 
if DEBUG
pusha
movzx eax, bx;save_cx_d;point_default
mov cx, 0x0a
mov di, RamdiskSector_msg
mov dword[ds:di], ' '
mov dword [ds:di+4], ' '
call decode
;Show size
mov si, RamdiskSector_msg
call printplain
 
popa
end if
 
; pop di
; pop es
}
 
macro use_RamdiskCluster
{
;для некоторых FS будет игнорироваться
; push es
; push di
mov di, point_default ;restore value
mov cx, save_cx_d
; push ini_data_
; pop es
.start_RamdiskCluster:
call get_firs_sym ;get first symbol on new line
test cx, cx
jz .end_RamdiskCluster ;нету? ну ладно - следующее значение тогда )
cmp al, 'R'
jnz .start_RamdiskCluster
;проверка на значения RamdiskSize
; parse_RamdiskSize
 
mov bx, cx
mov ax, di
 
mov si, parse_RamdiskCluster
mov cx, parse_RamdiskCluster_e - parse_RamdiskCluster
repe cmpsb
jnz .RamdiskCluster_rest_val ;is not compare
 
sub bx, parse_RamdiskCluster_e - parse_RamdiskCluster;correct cx
add bx, cx
mov cx, bx
 
test status_flag, flag_found_RamdiskCluster ;оценка флагов
jz .correct_is_not_set_RamdiskCluster
 
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
; call printplain
; jmp .get_next_str
 
.correct_is_not_set_RamdiskCluster:
mov ax, 0x3d20 ;cut al=' ' ah='='
repe scasb
jcxz .end_get_RamSC_ERROR_1 ;not found param
cmp ah, byte [es:di-1] ;find '='
jnz .start_RamdiskCluster ; перейдем на начало и попробуем найти еще секцию
repe scasb ;cut ' '
inc cx
dec di
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@:
movzx ax, byte [es:di]
cmp al, '0'
jb .end_RamdiskCluster
cmp al, '9'
ja .end_RamdiskCluster
;;;;;;;;;;;;;;;;;;;
xor al, 0x30
 
jmp .end_RamdiskCluster
 
 
.RamdiskCluster_rest_val:
mov cx, bx
mov di, ax
jmp .start_RamdiskCluster
.end_get_RamSC_ERROR_1:
 
.end_RamdiskCluster:
if DEBUG
pusha
mov cx, 0x0a
mov di, RamdiskCluster_msg
; mov word[ds:di],' '
call decode
;Show size
mov si, RamdiskCluster_msg
call printplain
 
popa
end if
 
}
 
macro use_Loader_Image
;предназначен для загрузки образов выше 1 Мб.
;первоначальная версия загружает образ дискеты 1.44 мб
{
local .start_p_LI
local .exit
local .error_LI
local .rest_value_loop
local .found_end_str
mov di, point_default ;restore value
mov cx, save_cx_d
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
.start_p_LI:
call get_firs_sym ;get first symbol on new line
test cx, cx
jz .exit ;нету? ну ладно - следующее значение тогда )
cmp al, 'L'
jnz .start_p_LI
;проверка на значение LoaderModule
; parse_LoaderModule
mov bx, cx
mov ax, di
 
mov si, parse_LoaderImage
mov cx, parse_LoaderImage_e - parse_LoaderImage
repe cmpsb
jnz .rest_value_loop ;is not compare
 
sub bx, parse_LoaderImage_e - parse_LoaderImage;correct cx
add bx, cx
mov cx, bx
 
; test status_flag,flag_found_LM ;оценка флагов
; jz .correct_is_not_set_LI
 
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
; call printplain
; jmp .get_next_str
 
;.correct_is_not_set_LI:
mov ax, 0x3d20 ;cut al=' ' ah='='
repe scasb
jcxz .rest_value_loop_LI ;not found param timeout
cmp ah, byte [es:di-1] ;find '='
jnz .rest_value_loop_LI
repe scasb ;cut ' '
inc cx
dec di
;di указывает на начало блока информации, в cx длинна до конца секции.
;после загрузки заноситься значение занятой памяти.
;для того что бы загрузить модуль, воспользуемся callback сервисом
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader
;мы ее модифицируем до такого состояния dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем
;сохранили певые 2 word
push dword [es:di-6]
lea si, [di-6]
 
push word [es:di-2]
xor ax, ax
mov word [es:di-6], ax ;вносим нужные значения
;info_real_mode_size размер и указатель на область в которую можно загрузиться
mov ax, info_real_mode_size ;0x3000 ;следующий сегмент за данными
 
 
mov word [es:di-4], ax
mov word [es:di-2], 16 ;кол-во блоков по 4 кб =64 кб т.е. больше не считаем
;;;;;; поиск конца строчки
@@:
mov al, byte [es:di]
cmp al, ' '
jz .found_end_str
cmp al, 0xa
jz .found_end_str
cmp al, 0xd
jz .found_end_str
inc di
dec cx
jnz @b
;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки
.found_end_str:
; чтение блока по 64 кб в сегмент и забрасывание его выше 1 мб.
push word [es:di]
xor ax, ax
mov word [es:di], ax
; xor ax,ax ; function 1 - read file
mov di, si ;file_data
inc ax
push si
push es
call far dword [loader_callback]
push cs
pop ds
 
pop es
pop si
 
test bx, bx
jnz .error_LM
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; забрасывание блока в 64 кб выше 1 мб.
mov si, table_15_87
push es
push ds
pop es
mov cx, 256*18
mov ah, 0x87
int 0x15
pop es
pop dx cx
test ah, ah
 
 
 
jmp far dword [es:si]
 
 
 
 
.rest_value_loop:
mov di, ax
mov cx, bx
jmp .start_p_LI
 
.exit:
 
 
 
}
 
 
 
macro name_in_root_fat
;макрос, который записывает информацию о загруженном файле в корневую фат таблицу
{
 
}
 
 
 
macro use_RamdiskFile
{
;загрузка файлов с использование callback сервиса первичного загрузчика
;используется только для загрузки необходимых и небольших файлов, т.к. достаточно медленно работает
;для загрузки использует 0х87 функцию int 0x15 прерывания - загрузка блоков данных до 64 кб выше 1 мб
local .start_loop
local ._end
local .rest_value_loop
local .error
mov di, point_default ;restore value
mov cx, save_cx_d
mov data_offset, 0 ;clean offset
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
.start_loop:
call get_firs_sym ;get first symbol on new line
test cx, cx
jz ._end ;нету? ну ладно - следующее значение тогда )
cmp al, 'R'
jnz .start_loop
;проверка на значение RamdiskFile
mov bx, cx
mov ax, di
 
mov si, parse_RamdiskFile
mov cx, parse_RamdiskFile_e - parse_RamdiskFile
repe cmpsb
jnz .rest_value_loop ;is not compare
 
sub bx, parse_RamdiskFile_e - parse_RamdiskFile;correct cx
add bx, cx
mov cx, bx
; test status_flag,flag_found_LM ;оценка флагов
; jz .correct_is_not_set_LM
 
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
; call printplain
; jmp .get_next_str
 
;.correct_is_not_set_LM:
mov ax, 0x3d20 ;cut al=' ' ah='='
repe scasb
test ecx, ecx
jz .rest_value_loop ;not found param timeout
cmp ah, byte [es:di-1] ;find '='
jnz .rest_value_loop
repe scasb ;cut ' '
inc cx
dec di
 
mov save_di_RAMDISK, di
mov save_cx_RAMDISK, cx
;di указывает на начало блока информации, в cx длинна до конца секции.
;после загрузки заноситься значение занятой памяти.
;для того что бы загрузить модуль, воспользуемся callback сервисом
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
;это выглядит так: в ini файле существует строчка RamdiskFile = @menu,@menu
;мы ее модифицируем до такого состояния dw,dw,db'@menu',0 конечно сохранив те значения которые мы заменяем
;сохранили певые 2 word
 
;
@@:
mov al, byte [es:di]
cmp al, ',' ; т.е. ищем разделитель
jz .found_end_str
inc di
dec cx
jnz @b
;;;not found допустим,что это конец файла и он не имеет привычного завершения строки
.found_end_str:
; mov al,byte [es:di]
; cmp al,' ' ; убираем пробелы, если они есть
; jnz @f
; inc di
; dec cx
; jnz .found_end_str
 
;@@:
mov point_to_dest_file_name, di
inc di
;проверка индивидуальности имени файла
check_name_file
;/restore di - point and cx -size section
mov di, save_di_RAMDISK
mov cx, save_cx_RAMDISK
 
test al, al
jnz .start_loop ;если в al значение не =0, то такое имя уже существует в системе.
 
 
 
push dword [es:di-6]
lea si, [di-6]
 
push word [es:di-2]
push di
xor ax, ax
mov word [es:di-6], ax ;вносим нужные значения
;info_real_mode_size размер и указатель на область в которую можно загрузиться
mov ax, info_real_mode_size ;0x3000 ;следующий сегмент за данными
 
 
mov word [es:di-4], ax
mov word [es:di-2], 16 ;кол-во блоков по 4 кб =64 кб т.е. больше не читаем
 
mov di, point_to_dest_file_name
 
if DEBUG
pushad
; mov ax,di
mov cx, 0x0a
mov di, name_of_seg_get_64
mov dword[ds:di], ' '
mov word[ds:di+4], ' '
call decode
;Show size
mov si, name_of_seg_get_64
call printplain
 
popad
end if
 
push word [es:di]
push cx
xor ax, ax
mov word [es:di], ax
; xor ax,ax ; function 1 - read file
push di
mov di, si ;file_data
inc ax
push si
push es
push bp
 
push es
pop ds
push cs
pop es
 
call far dword [es:loader_callback]
 
 
push cs
pop ds
 
pop bp
pop es
pop si
 
cmp bx, 2
ja .error
; сейчас у нас в dx:ax размер файла, который мы загрузили.
; возможна ситуация, когда в bx=1 т.е. есть еще данные на диске
mov status_flag_loader_f, bx
 
shl edx, 16
mov dx, ax
; shr edx,10 ;размер файла в кб.
;;в edx размер в байтах.
mov save_file_size, edx
mov eax, edx
;восстановим полностью файл сценария
pop di
pop cx ;длинна остатка с 2-ой частью имени т.е. с именем назначением.
pop word [es:di]
pop di
pop word [es:di-2]
pop dword [es:di-6]
 
if DEBUG
pushad
mov cx, 0x0a
mov di, RamdiskFile_msg
mov dword[ds:di], ' '
call decode
;Show size
mov si, RamdiskFile_msg
call printplain
 
popad
end if
 
 
 
 
 
 
 
 
 
 
; загрузим чему у нас равен кластер
; mov ax,word [fat12_buffer.BPB_BytsPerSec] ;кол-во байтов в секторе может быть любое 512 1024 2048 4096 2 байта
; movzx bx,byte [fat12_buffer.BPB_SecPerClus] ;кол-во секторов в кластере
; imul ax,bx
;сейчас в eax размер кластера (512) байт
;в edx длина файла в байтах до 64 кб
;закиним файл за 1 мб
;1 нам нужно составить фат таблицу т.е. произвести разметку рамдиска, затем перенесем по адресу файл
 
;записать инфорамацию о файле в корневую директорию
register_file_in_fat
;перенести за 1 мб содержимое файла
move_file_up
 
;проверим, загружен ли до конца файл? т.е. если размер файла больше чем 64 кб, то будет подгружать оставшиеся блоки
cmp status_flag_loader_f, 0x1
jnz @f
;нужно дозагузить данные файла и перенести их за 1-ый мб согласно фат структуре
 
 
 
 
 
 
 
 
 
@@:
;тут организован цикл по загрузке файлов в корневую директорию
mov di, save_di_RAMDISK
mov cx, save_cx_RAMDISK
if DEBUG
pusha
xor ax, ax
int 0x16
popa
end if
 
 
jmp .start_loop
 
 
.error:
;call error.LoaderModule
;fixme!
.rest_value_loop:
mov di, ax
mov cx, bx
jmp .start_loop
 
._end:
;перенесем за 1-ый мб фат и рут дир
move_up_fat_and_root_d
 
 
 
 
 
 
;загрузка блока
; mov ah,0x87
; mov cx, ;size in byte
 
;es:si point to descripts
 
 
}
 
macro use_BPB_RAM ;закинуть самые первые 512 байт за 1-й мб
;данный макрос закидывает BPB структуру т.е. первые 512 байт, пока только фат12 за 1 мб
{
mov ax, fat12_buffer
mov si, table_15_87
add word [si+8*2+2], ax
push es
push ds
pop es
mov cx, 256 ;бут сектор укладывается в 512 байт 512/2=256
mov ah, 0x87
int 0x15
pop es
;add 512 byte for destination adress
; add dword [si+8*3+2], 512
; test ah, ah
; jz
if DEBUG
pusha
mov ax, word [si+8*2+2]
mov cx, 0x0a
mov di, BPB_msg
call decode
;Show size
mov si, BPB_msg
call printplain
popa
end if
}
macro first_create_fat_table
;данный макрос создает оформляет 3 первых байта fat таблицы, и устанавливает указатель на следующий блок, и вносит 0 значение
;для смещения в корневой таблице.
{
mov al, byte [fat12_buffer.BPB_Media]
 
 
push ds
 
 
mov di, info_real_mode_size
add di, 0x1000
 
if DEBUG
pushad
 
mov ax, info_real_mode_size
add ax, 0x1000
; mov ax,ds
mov cx, 0xa
mov di, first_entry_in_fat
mov dword [di], ' '
mov word [di+4], ' '
call decode
;Show size
mov si, first_entry_in_fat
call printplain
 
xor ax, ax
int 0x16
popad
end if
 
 
push di ; push word info_real_mode_size+0x1000 ;cледующий сегмент за загруженным участком
xor di, di
mov point_to_free_root, di ;значение смещения =0 в корневой фат таблице описания
 
pop ds ; загружен следующий сегмент т.е. пустой сегмент
 
mov byte [di], al
or ax, -1
inc di
mov word [di], ax
 
pop ds
mov point_next_fat_str, 3
 
if DEBUG
pushad
mov ax, point_next_fat_str
mov cx, 0x0a
mov di, fat_create_msg
call decode
;Show size
mov si, fat_create_msg
call printplain
popad
end if
 
}
macro register_file_in_fat
;макрос регистрации файла в файловой структуре Fat
;пока поддерживается только фат12, пока ))
;вычисление смежных кластеров и занесение инфы в fat/
{
local .step2
local .step3
local .end
local .eof_file
 
;di point on root dir на фри секцию.
push es
 
mov ax, info_real_mode_size
add ax, 0x1000
mov es, ax ; push word info_real_mode_size+0x1000 ;сегмент следующий за загруженным блоком в 64 кб
 
; определяем тип фат пока не определяем, пока только фат 12
; 12 бит, для вычесления соседних каластеров.
mov di, firstDataSect ;в секторах
sub di, size_root_dir
;теперь в ax размер в секторах начала рут дир
shl di, 9;imul 512
add di, point_to_free_root ;смещение в уже записанных 32-х структурах.
;необходимо внести значение в рут дир т.е. 32 байта
if DEBUG
pushad
; mov ax,point_default
; mov ax,
mov cx, 0x0a
mov di, show_db2
mov dword[ds:di], ' '
mov word [ds:di+4], ' '
call decode
;Show size
mov si, show_db2
call printplain
;
; xor ax,ax
; int 0x16
popad
end if
 
 
 
;gs:di - указатель для внесения инфорации в рут область фат таблицы инормации о файле.
mov si, shot_name_fat
mov cx, 11
;запишем в структуру имя
@@:
lodsb
stosb
loop @b
 
;запишем атрибуты файла и DIR_NTRes - зарезеврированный байт =0
xor ax, ax
mov ah, ATTR_VOLUME_ID
mov word [es:di], ax
add di, 2
;DIR_CrtTimeTenth
mov byte [es:di], 100
inc di
;DIR_CrtTime
mov word [es:di], 0x032b ;дата
add di, 2
;DIR_CrtDate
mov word [es:di], 0x0 ;время ><
add di, 2
;DIR_LstAccDate
mov word [es:di], 0x032b ;дата моего
add di, 2
;DIR_FstClusHI
mov word [es:di], 0x0 ;время для фат12 /16 всегда 0
add di, 2
;DIR_WrtTime
mov word [es:di], 0x0 ;время ><
add di, 2
;DIR_WrtDate
mov word [es:di], 0x032b
add di, 2
mov ax, point_next_fat_str
mov word [es:di], ax
add di, 2
 
push di
;DIR_FstClusLO Младшее слово номера первого кластера.
; mov ax,point_next_fat_str ;загрузим указатель на элемент фат таблицы т.е. это номер фат записи
;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат
mov bx, ax
shr bx, 1
add ax, bx
;в ах сейчас FATOffset
;ThisFATEntOffset = BPB_ResvdSecCnt + (FATOffset / BPB_BytsPerSec);
mov bx, word [fat12_buffer.BPB_BytsPerSec]
cwd
idiv bx
;ax=ThisFATEntOffset= rem (FATOffset / BPB_BytsPerSec) четный или нечетный указатель.
mov si, ax
;нам нужно в цикле записать все кластеры которые будут использованы для размещения файла.
;узнаем размер кластера.
movzx eax, word [fat12_buffer.BPB_BytsPerSec]
movzx ebx, byte [fat12_buffer.BPB_SecPerClus]
imul eax, ebx
;ax - размер кластера.
;сейчас будем записывать во временный буфер фат таблицу для выбранного файла. Поскольку мы его загрузили возможно не полностью
;мы обработаем запись для фат полностью, в не зависимости от предела буфера где возможна часть файла.
mov ebx, save_file_size ;размер файла в байтах
@@:
sub ebx, eax
cmp ebx, eax
jbe .eof_file
 
inc point_next_fat_str
mov cx, point_next_fat_str ;загрузим указатель на элемент фат таблицы т.е. это номер фат записи
;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат
mov dx, ax
shr dx, 1
add cx, dx
 
 
 
test si, 0x1
jz .step2
shl cx, 4
mov word[es:si], cx
inc si
add cx, ax
jmp @b
 
.step2:
and cx, 0x0FFF
mov word[es:si], cx
inc si
add cx, ax
jmp @b
 
.eof_file:
mov cx, 0x0fff
test si, 0x1
jz .step3
shl cx, 4
mov word[es:si], cx
jmp .end
 
.step3:
and cx, 0x0FFF
mov word[es:si], cx
 
.end:
inc point_next_fat_str
 
pop di
;DIR_FileSize 32-битный DWORD содержит размер файла в байтах.
mov eax, save_file_size
mov dword [es:di], eax
 
if DEBUG
pushad
 
mov di, firstDataSect ;в секторах
sub di, size_root_dir
;теперь в ax размер в секторах начала рут дир
shl di, 9;imul 512
add di, point_to_free_root ;смещение в уже записанных 32-х структурах.
 
push di
 
mov si, dest_name_fat
mov cx, 11
 
;запишем в структуру имя
@@:
mov al, byte [es:di]
inc di
mov byte [ds:si], al
inc si
loop @b
mov di, si
inc di
pop ax
mov cx, 0xa
call decode
 
mov si, dest_name_fat
call printplain
popad
 
END IF
 
 
 
 
 
add point_to_free_root, 32 ;увелицим смещение до следующего значения.
pop es
 
}
 
 
 
 
 
macro get_firstDataSector
;макрос для вычисления певого сектора данных т.е. данных файлов в фате
;вычислим FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors;
{
mov ax, word [fat12_buffer.BPB_FATSz16]
movzx bx, byte [fat12_buffer.BPB_NumFATs]
imul ax, bx ;9x1=9
;ax=BPB_NumFATs * FATSz
mov bx, word [fat12_buffer.BPB_RootEntCnt] ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
shr bx, 4 ;imul bx,32 and then div 512 -> in bx size in sectors
add ax, bx ;9+14=23
mov size_root_dir, bx
movzx bx, byte [fat12_buffer.BPB_RsvdSecCnt] ;add 1 for fat 16/12
add ax, bx
;ax=firstDataSector - где начинается первый секторо от 0 сектора в секторах. - фактически = 24 сектор
mov firstDataSect, ax ;сохраним для вычисления
; получимзначение кластеров, это объем в который мы можем записать данные
mov bx, word [fat12_buffer.BPB_TotSec16]
sub bx, ax
mov ax, bx
movzx bx, byte [fat12_buffer.BPB_SecPerClus]
cwd
idiv bx
mov DataClasters, ax
 
if DEBUG
pushad
mov ax, firstDataSect ;первый сектор данных
mov cx, 0x0a
mov di, firstDataSect_msg
call decode
;Show size
mov si, firstDataSect_msg
call printplain
;;;;;;;;;;;;;;;;;;;;;;;;;;
mov ax, size_root_dir ;размер рут дир в сетокторах
mov cx, 0x0a
mov di, size_root_dir_msg
call decode
;Show size
mov si, size_root_dir_msg
call printplain
;;;;;;;;;;;;;;;;;;;;;;;;;;
mov ax, DataClasters;кластеры
mov cx, 0x0a
mov di, DataClasters_msg
call decode
;Show size
mov si, DataClasters_msg
call printplain
popad
 
end if
 
}
 
macro use_RamdiskPATHS
;парсинг пути источника файлов.
{
 
}
 
macro use_RamdiskPATHD
;парсинг пути назначения файлов.
{
 
}
macro check_name_file
;макрос проверки имени на повтор, имя должно быть уникальным.
;входные данные: es- сегмент где лежит файл для парсинга т.е. startos.ini
;di - указатель на имя файла т.е. es:di указывает на имя файла назначения
;выходные данные eax =-1 имя совпало, eax=0 имя не совпало.
{
local .no_equal
local .exit
local .loop_size_root_dir
;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными.
;преобразуем в аналог фат записи сточку с именем назначения
convertion_file_name ; преобразовали имя по нужным правилам
test ax, ax
jnz .exit
 
lea si, [shot_name_fat] ; desination name of file
 
;вычислим указатель на корневую директорию
mov di, firstDataSect
sub di, size_root_dir
;теперь в ax размер в секторах начала рут дир
shl di, 9;imul 512
;di= Это смещение от начала буфера до рут директории. в пределах 64 кб.
;загрузим значение - т.е. кол-во элементов, которые мы можем просматривать.
mov dx, root_dir_entry_count
mov ax, info_real_mode_size
add ax, 0x1000
 
 
mov gs, ax
.loop_size_root_dir:
DEBUG1 equ 0
if DEBUG1
pushad
push di
mov eax, dword[gs:di]
lea si, [check_root_fat_+14]
mov dword [ds:si], '----'
mov dword [ds:si+4], '----'
mov dword [ds:si+8], '----'
mov dword[ds:si], eax
mov eax, dword[gs:di+4]
mov dword[ds:si+4], eax
mov eax, dword[gs:di+8]
mov dword[ds:si+8], eax
 
;
xor eax, eax
mov ax, gs;point_next_fat_str
mov cx, 0x0a
mov di, check_root_fat_
mov dword [di], ' '
mov word [di+4], ' '
call decode
xor eax, eax
pop ax
mov di, (check_root_fat_+7)
mov dword [di], ' '
mov word [di+4], ' '
call decode
 
;Show size
lea si, [check_root_fat_]
call printplain
 
lea si, [shot_name_fat]
call printplain
 
xor ax, ax
int 0x16
popad
end if
 
xor bx, bx
mov cx, 11 ;size of name in struct FAT
 
@@:
mov al, byte [ds:si+bx] ;ds:si - point to name of convertion variable.
mov ah, byte [gs:di+bx] ;gs:di - point to name in fat struct
inc bx
 
if DEBUG
; pushad
; lea si,[check_root_fat_+14]
; mov dword [ds:si],'----'
; mov word [ds:si],ax
; call printplain
 
; xor ax,ax
; int 0x16
 
; popad
end if
 
 
 
cmp ah, al
jnz .no_equal
 
; dec cx
; jnz @b
loop @b
 
;.succesfuly:
;печально, такое имя уже имеется :(
or ax, -1
jmp .exit
 
 
.no_equal:
add di, 32 ;fat struct =32 byte
dec dx
jnz .loop_size_root_dir
 
;.exit_check_name:
and ax, 0
 
.exit:
 
if DEBUG
pushad
;Show size
lea si, [check_name_fat_msg_n]
test ax, ax
jz @f
lea si, [check_name_fat_msg_y]
call printplain
lea si, [alarm_msg]
@@:
call printplain
popad
end if
 
}
 
 
macro convertion_file_name
;макрос конвертации имени, это нужно поскольку формат представленный не соответсвует фат и напрямую редко можно когда использовать
;преобразование имени типа hello.asm в 'HELLO ASM', в соответствии с правилами fat.
;входные параметры es:di указатель на имя файла которое нужно преобразовать, конечный буфер shot_name_fat
{
local .next_step
local .error
local .st1
local .st2
local .st2_l
local .st3
local .st4_s
local .st4
local .st5
 
;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными.
; mov di,point_to_dest_file_name входной параметр
mov si, shot_name_fat
or first_input, -1 ;при первом входе устанавливаем флаг
mov cx, 11 ;длинна имени в стуктуре фат таблицы
 
@@:
mov al, byte [es:di]
cmp al, 0xa
jz .st4_s
cmp al, 0xd
jz .st4_s
cmp al, 0x20
jz .st4_s
 
cmp al, 0x20
jb .error
cmp al, 0x22
jz .error
cmp al, 0x2a
jz .error
cmp al, 0x2b
jz .error
cmp al, 0x2c
jz .error
cmp al, 0x2F
jz .error
 
cmp al, 0x3a
jz .error
cmp al, 0x3b
jz .error
cmp al, 0x3c
jz .error
cmp al, 0x3d
jz .error
cmp al, 0x3E
jz .error
cmp al, 0x3F
jz .error
 
cmp al, 0x5b
jz .error
cmp al, 0x5c
jz .error
cmp al, 0x5d
jz .error
 
cmp al, 0x7c
jz .error
 
cmp first_input, -1
jnz .next_step
and first_input, 0 ;сборосим флаг.
cmp al, '.'
jz .error ;обработка точки, файл не может начинаться с точки
 
.next_step:
cmp al, 0x2e
jnz .st2 ;обработка точки, в середине файла
;тут у нас установлен разделитель
;все остальнео место займут пробелы
mov al, ' '
 
;!fixme обработаны не все исключения :(
cmp cl, 3 ;формат файла такой GIDGIDIIASM т.е. gidgidii.asm
jbe .st2
 
 
.st3:
mov byte [si], al
inc si
dec cx
cmp cx, 3
ja .st3
; inc cx
inc di
jmp @b
 
.st2:
cmp al, 0x60
jbe .st2_l
xor al, 0x20;сделаем заглавные буквы
.st2_l:
mov byte [si], al
inc di
inc si
; dec cx
; jnz @b
loop @b
.st5:
xor ax, ax
jmp @f
 
;;;;;;;;файл закончился, и нужно внести в конец пробелы
.st4_s:
mov al, ' '
.st4:
mov byte [si], al
inc si
loop .st4
jmp .st5
 
.error:
or ax, -1
@@:
 
if DEBUG
pushad
mov si, convertion_file_name_msg_y
test ax, ax
jz @f
mov si, convertion_file_name_msg_n
@@:
call printplain
 
mov si, shot_name_fat
mov byte [si+12], 0
call printplain
popad
 
end if
}
 
macro move_file_up
;макрос который перемещает за 1 мб с правилами фат данные файла.
{
local .st1
local .correct_on_byte
;сейчас имеет быть ситуация, когда BPB уже перемещен за 1 мб, фат, и рут дир будут позже перемещены,
;а нам нужно вычислить место, и перенести туда содержимое файла
;полученое значение указывает в байтах на начало данных
 
mov ax, info_real_mode_size ; сегмент где расположены данные
mov si, table_15_87
mov word [si+8*2+2], ax
;смещение до данных уже за 1-м мб
movzx eax, firstDataSect
movzx edx, data_offset
add eax, edx
 
movzx ebx, word [fat12_buffer.BPB_BytsPerSec]
movzx edx, byte [fat12_buffer.BPB_SecPerClus]
imul bx, dx ;получим размер кластера
 
 
 
push ebx ;save bx
 
imul eax, ebx
; shl eax,9 ;умножим на 512
if DEBUG
pushad
xor eax, eax
mov ax, info_real_mode_size
mov cx, 0x0a
mov di, seg_where_get_data
mov dword [di], ' '
mov word [di+4], ' '
call decode
;Show size
mov si, seg_where_get_data
call printplain
popad
 
end if
 
; mov bx,word [fat12_buffer.BPB_BytsPerSec]
; movzx dx,byte [fat12_buffer.BPB_SecPerClus]
; imul bx,dx
; cwd
; idiv bx
 
mov dl, 0x10
 
@@:
cmp eax, 0x00010000
jb @f
 
sub eax, 0x00010000
inc dl
jmp @b
 
 
@@:
mov byte [si+8*3+3], dl ;куда писать
mov word [si+8*3+2], ax
 
mov ecx, save_file_size ;размер файла в байтах.
cmp ecx, 0x0000ffff ;размер блока т.е. 64 кб
jbe .correct_on_byte ;корректировка на байт значения
 
 
 
mov ecx, 0x00010000 ;65536
sub save_file_size, ecx ;отнимим
; jmp .st1 ;получим 0х8000
 
 
 
 
;корректировка значения должна быть выполенена на размер кластера
.correct_on_byte:
;/узнаем размер кластера
pop eax ;restore size of claster
push ecx
@@:
inc data_offset
 
cmp eax, ecx
jae @f
sub ecx, eax
jmp @b
@@:
pop ecx
 
 
 
 
test ecx, 0x1
jz .st1
inc ecx
.st1:
shr ecx, 1 ; преобразовать значение для 0x87 function
 
;перенесем блок за 1 мб
push es
push ds
pop es
 
mov ah, 0x87
int 0x15
pop es
 
if DEBUG
pusha
; mov ax,point_next_fat_str
mov cx, 0x0a
mov di, return_code_af_move
call decode
;Show size
mov si, return_code_af_move
call printplain
popa
 
end if
 
}
 
 
macro move_up_fat_and_root_d
;макрос, который позволяет перенести выше 1 мб в структуру образа фат таблицу и рут директорию
{
local .st1
 
mov ax, info_real_mode_size
add ax, 0x1000
 
mov si, table_15_87
mov word [si+8*2+2], ax
;смещение до данных
mov ax, 512
mov word [si+8*3+2], ax
;fixme! тут необходимо сделать подержку т.е. формировать смещение файла в уже записанных данных.
 
movzx ecx, word [fat12_buffer.BPB_FATSz16]
movzx bx, byte [fat12_buffer.BPB_NumFATs]
imul cx, bx ;9x1=9
 
add cx, size_root_dir ;размер корневой дирректории
shl ecx, 9 ;imul 512
 
 
;корректировка значения
test ecx, 0x1
jz .st1
inc ecx
.st1:
shr ecx, 1
 
push es
push ds
pop es
 
mov ah, 0x87
int 0x15
pop es
 
if DEBUG
pusha
; mov ax,point_next_fat_str
mov cx, 0x0a
mov di, return_code_af_fat_m
call decode
;Show size
mov si, return_code_af_fat_m
call printplain
popa
 
end if
 
}
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/parse_err.inc
0,0 → 1,66
; Copyright (c) 2009, <Lrz>
; 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.
;*****************************************************************************
 
error:
.rest_value:
mov di, ax;restore value after repe cmpsb
mov cx, bx
jmp ret_on_ch ;return
 
;///// ошибка при находжении длинны секции в параметре default
.error_get_size_d_sect:
leave ;clear array in stack
mov si, not_found_def_sect
jmp err_show_ini
 
;/////ERROR
.not_loader:
leave ;clear array in stack
mov si, not_found_sec_loader
jmp err_show_ini
 
.default_eq_loader: ;критическая ошибка default секция = loader
leave
mov si, default_eq_loader
jmp err_show_ini
.correct_exit_bl:
leave
mov si, point_to_default_sec_not_found
jmp err_show_ini
.incorect_section_def:
leave
mov si, incorect_section_define
jmp err_show_ini
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;show message error
.LoaderModule:
push word 0xb800
pop es
 
 
 
ret
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/parse_loader.inc
0,0 → 1,335
; Copyright (c) 2009, <Lrz>
; 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 nickname <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.
;*****************************************************************************
 
;блок макросов по обработке секции [loader]
;входные данные:
;es:di - указатель на секцию начинающиюся с '[' встечающиюся после 0хa
;cx - счетчик кол-во байт для проверке в кадре
;
macro use_parse_loader
{
.parse_loader:
;//////////////////
;/ parse [loader]
;//////////////////
mov bx, cx ;cохраним в регистры значения счетчика и указателя
mov ax, di
 
; mov word [bp-4],.start ;is alredy set, see up
mov si, parse_loader
mov cx, parse_loader_e - parse_loader
repe cmpsb
jnz error.rest_value ;цепочка не совпала :( перейдем далее т.е. будем снова искать))
 
;сохраним указательна loader, что бы потом больше его не искать
mov point_loader, ax
sub bx, parse_loader_e - parse_loader;correct cx
add bx, cx
mov cx, bx
 
if DEBUG
pusha
mov si, lm_l_found
call printplain
popa
end if
;/////////////////end check [loader]. [loader] is found
;parsing section [loader]
;first found end section,let's found '[' -it's start next section
;in previosly steep bx =cx we are not need save cx, save only di - point
mov dx, di
@@:
call get_firs_sym
jcxz .loader_f_end ;.end_loader ; end даже если мы не нашли секцию предположим что секция [loader] стоит в конце
cmp al, '['
jnz @b
 
.loader_f_end:
sub bx, cx ;bx = n byte presend in section [loader]
mov di, dx ;restore di
;////////////////parse parametrs in section [loader]
;//timeout=5
;//default=main
; mov di,dx ;set pointer on section [loader] i think it's not need
mov cx, bx ;set counter for parsing section [loader] cx= кол-ву символов в секции [loader]
mov ret_on_ch, .get_next_str; return point
;;;;;;; parse timeout & default
.get_next_str:
call get_firs_sym ;get first symbol on new line
 
test cx, cx
jz .end_loader
; jcxz .end_loader ;завершение парсинга значений timeout & default
cmp al, 't'
jz .loader_timeout
cmp al, 'd'
jnz .get_next_str
;//////[loader].default
;input di point to data cx=size [loader]
mov bx, cx
mov ax, di
 
mov si, parse_l_default
mov cx, parse_l_default_e - parse_l_default
repe cmpsb
 
jnz error.rest_value ;is not compare цепочка не совпала
 
sub bx, parse_l_default_e - parse_l_default;correct cx
add bx, cx
mov cx, bx
 
test status_flag, flag_found_default
jz .correct_is_not_set
 
mov si, found_equal_default ;мы нашли что флаг уже установлен, информируем
call printplain
jmp .get_next_str
 
.correct_is_not_set:
mov ax, 0x3d20 ;cut al=' ' ah='='
repe scasb
test cx, cx
jz .end_loader
cmp ah, byte [es:di-1] ;find '='
jnz .get_next_str
repe scasb ;cut ' '
inc cx
dec di
;сейчас es:di указывают на название секции, имя секции по дефолту не должно быть loader т.е. иначе возможно зацикливание
;установим указатель si на это значение и сначала проверим
 
;получение длинны секции
; cx=bx содержит длинну остатка секции
; di=ax указатель на текущию секцию
mov bx, cx
mov dx, di
 
@@:
mov al, byte [es:di]
inc di
dec cx
test cx, cx
jz error.error_get_size_d_sect ;переход на обработку ошибки по нахождению длины дефолтной секции
cmp al, ' '
jz @b
cmp al, 0xd
jz .found_size_d_sect
cmp al, 0xa
jnz @b
.found_size_d_sect:
;
inc cx ;correct cx
mov ax, bx
sub bx, cx ; в bx длина секции которая определена по дефолту
mov save_cx_d, bx
mov di, dx
 
mov cx, bx ;set size default section
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;проверка на =loader
;save in reg point and счетчик
;check on loader
mov bx, ax
mov ax, dx
 
mov si, parse_loader
inc si ;set only loader and 6 char in counter
repe cmpsb
jnz .check_section ;цепочка не совпала :( перейдем далее )) значит не исключение
 
jmp error.default_eq_loader ;error критическая ошибка т.е. в дефолте присутствует имя [loader]
 
.check_section: ;поиск соответствующей секции нам нужно будет узнать адрес этой секции
mov cx, bx
mov di, ax
 
;/////////////////////////////
; mov ret_on_ch,.start_d ;set return
mov si, di ;установим указатель на нашу секцию, которая по дефолту
 
push di ;save point di
 
push cx ;save cx
;установим указатель es:di на начало ini файла
mov cx, save_cx ;it's placed size of ini file
les di, dword [file_data]
 
 
mov al, byte [es:di]
push word .first_ret_d
cmp al, ' '
jz .first_sp_1_d
jmp get_firs_sym.not_space
.first_sp_1_d:
jmp get_firs_sym.first_sp
 
.start_d:
call get_firs_sym ;get first symbol on new line
.first_ret_d: ;первый возврат
jcxz .correct_exit ;.end_loader ;found or not found parametrs in section exit in section
cmp al, '['
jz .found_sect_d
jmp .start_d
;просматриваем ini файл с начала в поисках секции указаной как default
;идет проверка на наличее значения timeout, для более быстрой работы, этот параметр должен быть уже обработан,т.е. в этом случае при его =0 будет сформирован указатель только на дефолтную секцию, иначе информация будет собрана по всем секциям и составлены указатели в блоке памяти
.found_sect_d:
 
;check on name section
mov bx, cx
mov ax, di
push si ;save point
; mov si,parse_loader
mov cx, save_cx_d;load size section
push es
pop ds
 
inc di
repe cmpsb
push cs
pop ds
pop si
jnz .not_compare_d_s ;цепочка не совпала :( перейдем далее )) значит не исключение
cmp byte[es:di], ']'
jnz .not_compare_d_s ;нет в конце нашей секции завершающего символа :(
 
 
 
;set flag -we have found default -not enter again in this prosedure
or status_flag, flag_found_default
pop cx
pop di
mov point_default, ax ;point to [
 
if DEBUG
pusha
mov si, lm_lf_default_f
call printplain
popa
end if
jmp .get_next_str
 
.not_compare_d_s:
 
mov cx, bx
mov di, ax
jmp .start_d
 
.correct_exit:
pop cx ;восстановим значение счетчика
pop di
 
 
if DEBUG
pusha
mov si, lm_lf_default
call printplain
popa
end if
jmp .get_next_str
 
;//////////[loader].timeout
.loader_timeout:
mov bx, cx
mov ax, di
 
mov si, parse_l_timeout
mov cx, parse_l_timeout_e - parse_l_timeout
repe cmpsb
jnz error.rest_value ;is not compare
 
sub bx, parse_l_timeout_e - parse_l_timeout;correct cx
add bx, cx
mov cx, bx
 
test status_flag, flag_found_timeout
jz .correct_is_not_set_t
 
mov si, found_equal_timeout ;мы нашли что флаг уже установлен, информируем
call printplain
jmp .get_next_str
 
.correct_is_not_set_t:
mov ax, 0x3d20 ;cut al=' ' ah='='
repe scasb
jcxz .timeout_sec_end_d ;not found param timeout
cmp ah, byte [es:di-1] ;find '='
jnz .get_next_str
repe scasb ;cut ' '
inc cx
dec di
;get timeout value
;2 знакa может быть обработано т.е. значение от 0 до 99 секунд
push cx
xor bx, bx
mov cx, 2
@@:
mov al, byte [es:di]
cmp al, '0'
jb .end_get_val_t
cmp al, '9'
ja .end_get_val_t
imul bx, 10
xor al, 0x30
add bl, al
.end_get_val_t:
inc di
loop @b
mov word [value_timeout], bx
; pop cx
 
if DEBUG
pusha
mov si, lm_lf_timeout
call printplain
popa
end if
 
jmp @f
.timeout_sec_end_d:
mov word [value_timeout], default_timeout_value
mov si, set_default_timeout_val
call printplain
@@:
pop cx
jmp .get_next_str
 
;///////here end block loader
.end_loader:
if DEBUG
pusha
mov si, lm_l_end
call printplain
popa
end if
 
}
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/sl_equ.inc
0,0 → 1,98
; Copyright (c) 2008-2009, <Lrz>
; 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.
;*****************************************************************************
; Предопределения
DEBUG equ 1 ;компиляция с отладочной информацией =1 без отладочной инфорации =0
loop_read_startos_file equ 3 ;кол-во попыток считать через callback сервис файл конфигурации блок2
root_dir_entry_count equ 224 ;кол-во элементов в корневой дирректории
;point_to_fat_struc equ 0xA000 ;временный буфер, куда будет размещена Fat таблица, и затем перенесена за 1 мб
ini_data_ equ 0x2000 ;файл где размещен файл сценария загрузки, там происходит синтаксический разбор
size_show_section equ 18
default_timeout_value equ 5 ;default value to timeout is will was some errors
flag_found_default equ 0x1 ;default value is found
flag_found_timeout equ 0x2 ;timeout value is found
flag_found_LM equ 0x1 ;found LM value
flag_found_RS equ 0x2 ;found RS value
flag_found_GTRFMS equ 0x4 ;found type RamFS
flag_found_RamdiskSector equ 0x8 ;found RamdiskSector
flag_found_RamdiskCluster equ 0x16 ;found RamdiskCluster
;statick data эти данные не предопределяются в течении выполнения всей программы.
save_cx equ word [bp-2] ;save cx size ini file
ret_on_ch equ word [bp-4] ;point to return разрушаемое значение
save_cx_d equ word [bp-6] ;save cx - size default section and working section
status_flag equ word [bp-8] ;status flag
point_loader equ word [bp-10]
point_default equ word [bp-12] ;point to default
 
;данные которые зависимы от ветки выполнения и которые могут быть переопределены в процессе выполнения программы.
point_to_hframe equ word [bp-14] ;point on start frame (for change section)
point_to_1 equ word [bp-16]
point_to_2 equ word [bp-18]
point_to_3 equ word [bp-20]
point_to_4 equ word [bp-22]
point_to_5 equ word [bp-24]
point_to_6 equ word [bp-26]
point_to_7 equ word [bp-28]
point_to_8 equ word [bp-30]
point_to_9 equ word [bp-32]
point_to_10 equ word [bp-34]
point_to_11 equ word [bp-36]
point_to_12 equ word [bp-38]
point_to_13 equ word [bp-40]
point_to_14 equ word [bp-42]
point_to_15 equ word [bp-44]
point_to_16 equ word [bp-46]
point_to_16 equ word [bp-48]
point_to_17 equ word [bp-50]
point_to_18 equ word [bp-52]
;here array for fast scroling 16 word - poin to start section
point_to_point_def equ word [bp-54]
point_to_eframe equ word [bp-56] ;point on point frame
 
 
 
; тут расположено временное хранилище для cx и di при переходе на следующий буфер при поиске секций
find_sec_di equ word [bp-58] ;тут будет храниться di
info_real_mode_size equ word [bp-60];тут храниться информация о занятой области т.е. размер, можно узнать сколько осталось места вычислив
free_ad_memory equ word [bp-62] ;сколько у нас расширенной памяти для формирования рам диска и загрузки модулей
show_errors_sect equ word [bp-64] ;переменая которая хранит биты ошибок для каждой логической секции.
save_descript_size equ word [bp-66] ;save descript size previos section сохраним размер предыдущей секции которую выводили
save_ramdisksize equ dword [bp-70] ;save size of ramdisk in byte
save_file_size equ dword [bp-74] ;save size of reading file
set_ramfs equ word [bp-76] ;определенный тип файловой системы,нужно для формирования рам диска
point_next_fat_str equ word [bp-78] ;указатель на следующий элемент fat таблицы
size_root_dir equ word [bp-80] ;кол-во элементов в секторах по 512 байт корневой директории
firstDataSect equ word [bp-82] ;первый сектор данных в сеторах от 0
DataClasters equ word [bp-84] ;размер массива доступной для записи данных в кластерах.
point_to_free_root equ word [bp-86] ;указатель на следующий пустую запись в рут дир
point_to_dest_file_name equ word [bp-88] ;указывает на начало имени файла назначения. в формате es:point_to_dest_file_name, где es =0x2000
data_offset equ word [bp-90] ;смещение в кластерах для записанных данных т.е перекинутых за 1-й мб
first_input equ word [bp-92] ;поле для флагов в преобразовании имени.
save_di_RAMDISK equ word [bp-94] ;сохраним di -указателя при обработке секции
save_cx_RAMDISK equ word [bp-96] ;сохраним размер остатка секции
status_flag_loader_f equ word [bp-98] ;сохраним результат выполенения загрузки файла
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;данные которые используются при обработке секции, т.е. после нажатия Enter, уже не возможно вернуться в первоначальный экран
;для возврата, необходимо перезапустить полностью код т.е. стартовать с 0х1000:0000
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/sl_proc.inc
0,0 → 1,528
; Copyright (c) 2009, <Lrz>
; 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.
;*****************************************************************************
 
; тут описываются процедуры которые используются в secondary loader
color_sym_black equ 0
color_sym_blue equ 1
color_sym_green equ 2
color_sym_turquoise equ 3
color_sym_red equ 4
 
color_sym_lightgray equ 7
 
color_sym_lightblue equ 9
color_sym_lettuce equ 10
color_sym_pink equ 12
color_sym_yellow equ 14
color_sym_white equ 15
if DEBUG
decode:
;input eax - число, es:di куда писать, cx=10
cmp eax, ecx
jb @f
xor edx, edx
div ecx
push edx
call decode
pop eax
@@:
or al, 0x30
mov [ds:di], al
inc di
ret
 
end if
 
 
putchar:
; in: al=character
mov ah, 0Eh
mov bh, 0
int 10h
ret
 
printplain:
; in: si->string
pushad
lodsb
@@:
call putchar
lodsb
test al, al
jnz @b
mov al, 13
call putchar
 
mov al, 10
call putchar
popad
ret
getkey:
; get number in range [bl,bh] (bl,bh in ['0'..'9'])
; in: bx=range
; out: ax=digit (1..9, 10 for 0)
mov ah, 0
int 16h
cmp al, bl
jb getkey
cmp al, bh
ja getkey
push ax
call putchar
pop ax
and ax, 0Fh
jnz @f
mov al, 10
@@:
ret
 
;setcursor:
; in: dl=column, dh=row
; mov ah, 2
; mov bh, 0
; int 10h
; ret
 
;macro _setcursor row,column
;{
; mov dx, row*256 + column
; call setcursor
;}
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
get_firs_sym:
.start:
mov al, byte [es:di]
inc di
dec cx
jcxz .exit
 
cmp al, 0xa ;cmp al,0xa
jz ._entry
 
cmp al, ';'
jnz .start
 
.first_com:
 
mov al, 0xa
repnz scasb
jcxz .exit
._entry:
mov al, byte [es:di]
.first_sp:
cmp al, ' '
jnz .not_space
 
; mov al,' ' ;cut ' '
repe scasb
dec di
inc cx
mov al, byte [es:di]
.not_space:
cmp al, ';'
jz .first_com
.exit:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
show_name_section:
push si
push ini_data_
pop es
 
 
mov al, ']'
repnz scasb
test cx, cx
jz error.incorect_section_def
.find_val_name_fb1:
mov al, 'n'
.find_val_name_fb:
repnz scasb
jcxz .not_name_sec_fb
 
mov si, parse_name
 
push cx
push di
 
mov cx, parse_name_e -parse_name
repe cmpsb
pop di
pop cx
jz .yaaa_find_value
 
 
jmp .find_val_name_fb
 
.yaaa_find_value:
sub cx, parse_name_e -parse_name
add di, parse_name_e -parse_name
 
mov ax, 0x3d20 ; ah='='
repe scasb
test cx, cx
jz .not_name_sec_fb
 
cmp ah, byte [es:di-1] ;find '='
jnz .find_val_name_fb1
repe scasb ;cut ' '
inc cx
dec di
 
 
;все вырезали и все готово для вывода имени секции ))
push es
pop ds
 
.def_sect_name:
push 0xb800
pop es
;clear array for message
xor ax, ax
if DEBUG
mov ax, 0x0720
end if
 
mov cx, 39
mov si, di
mov di, dx
sub di, 2
rep stosw
;//////////////////////
 
 
mov di, dx
mov ah, color_sym_white;color_sym_lightblue
mov cx, 36
lodsb
sub di, 2
cmp al, '"'
jz @f
cmp al, "'"
jnz .end_sh_name_sec
@@:
lodsb
@@:
stosw
lodsb
cmp al, '"'
jz .end_sh_name_sec
cmp al, "'"
jz .end_sh_name_sec
loop @b
mov al, '}'
mov ah, color_sym_yellow
stosw
.end_sh_name_sec:
push cs
pop ds
 
pop si
ret
 
.not_name_sec_fb: ;нет имени в названии секции - значит так и скажем об этом
push cs
pop ds
mov di, default_section_name
jmp .def_sect_name
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;процедура поиска вверх следующей секции
;в point_default содержиться указатель на дефаулт секцию, и в пределах врейма мы бегаем по заранее пропарсеными значениям указателей
;для того что бы отобразить и пропарсить следующий фрейм, нам нужно получить за пердыдущий или следующий указатель
find_before_sect:
mov di, point_default
.e:
push ini_data_
pop es
mov cx, di ;предположим будем просматривать к началу, текущая позиция di = сколько символов от начала документа имеется
mov bx, cx ;копия
 
;настроили указатель на дефаулт секцию
;будем искать вверх
.find_start_section:
std ;установка флага направления - будем просматирвать к началу нашего ини файла
;будем искать начало секции т.е. '[' этот символ
mov al, 0xa
repnz scasb ;просканируем на наличее символа начала секции
jcxz .go_ ;мы просмотрели до начала файла, но так и ничего не нашли ;(( по тихому выйдем )
 
mov find_sec_di, di ;сохраним данные
mov cx, di ;
 
sub bx, cx
mov cx, bx ;в сx значение - кол-во символов
cld
call get_firs_sym
.ret_go:
jcxz ._not_section ; в данном случае имеем конструкцию 0xa ... ; hello [секция] обломс ищем далее
 
cmp di, point_loader; секцию loader мы не заносим иначе крах
jz ._not_section
;все удачно мы нашли вхождение секции предыдущей
cmp al, '['
jnz ._not_section
mov point_default, di
.exit_scan_sect:
ret
;;;;;;;; восстановим значения и продолжим поиски начала секции которая нас устроит ))
._not_section:
mov di, find_sec_di
mov cx, di
mov bx, cx
jmp .find_start_section
.go_:
cld
mov cx, bx ;в сx значение - кол-во символов
 
mov al, byte [es:di]
push word .f_go
cmp al, ' '
jz @f
jmp get_firs_sym.not_space
@@:
jmp get_firs_sym.first_sp
 
.f_go:
jcxz .exit_scan_sect ; в данном случае имеем конструкцию 0xa ... ; hello [секция] обломс ищем далее
 
cmp di, point_loader; секцию loader мы не заносим иначе крах
jz .exit_scan_sect
;все удачно мы нашли вхождение секции предыдущей
cmp al, '['
jnz .exit_scan_sect
mov point_default, di
ret
 
 
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
find_next_sect:
mov di, point_default
push ini_data_
pop es
mov cx, save_cx;di ;предположим будем просматривать к концу, текущая позиция di = сколько символов от начала документа имеется
sub cx, di ;сейчас в cx остаток т.е. сколько можно крутить до конца и не вылазить на начало
jmp .let_s_go
.h:
push ini_data_
pop es
mov cx, save_cx;di ;предположим будем просматривать к концу, текущая позиция di = сколько символов от начала документа имеется
; sub cx,di ;сейчас в cx остаток т.е. сколько можно крутить до конца и не вылазить на начало
 
mov al, byte [es:di]
push word .let_s_go_ret
cmp al, ' '
jz @f
jmp get_firs_sym.not_space
@@:
jmp get_firs_sym.first_sp
 
 
 
 
;настроили указатель на дефаулт секцию
;будем искать вниз
.let_s_go:
call get_firs_sym
.let_s_go_ret:
jcxz .exit_scan_sect ; в данном случае имеем конструкцию 0xa ... ; hello [секция] обломс ищем далее
cmp al, '['
jnz .let_s_go
cmp di, point_loader
jz .let_s_go
;все удачно мы нашли вхождение секции предыдущей
mov point_default, di
.exit_scan_sect:
ret
 
;;;;;;;;;;;;;;;;;;;;;;;;;;
;clean old cursor
clean_active_cursor:
;не изменяет значение ax
;отображение курсора по умолчанию
lea si, point_to_hframe
mov di, 962-160
mov dx, point_default
mov cx, 18
.clean_show_cur:
mov bx, [si]
add di, 160
cmp bx, dx
jz .clean_cursor_
sub si, 2
loop .clean_show_cur
 
; jmp $
 
.clean_cursor_:
push 0xb800
pop es
push ax
mov point_to_point_def, si
xor ax, ax
if DEBUG
mov ax, 0x0720
end if
stosw
add di, 68
stosw
pop ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;установка таймера и отображение счетчика времени
gettime:
mov ah, 0
int 1Ah
xchg ax, cx
shl eax, 10h
xchg ax, dx
ret
newtimer:
push ds
 
push cs
pop ds
 
pushf
call far dword [old_timer]
 
pushad
call gettime
 
sub eax, dword[start_timer]
mov bx, word [value_timeout]
imul bx, 18
sub bx, ax
jbe .timergo
 
push es
 
push 0xb800
pop es
mov ax, bx
 
mov bx, 18
xor dx, dx
div bx
 
mov bx, 10
mov di, 3734
call .decode
 
xor ax, ax
stosw
 
; wait 5/4/3/2 seconds, 1 second
pop es
popad
pop ds
 
iret
.timergo:
push 0
pop es
mov eax, dword [old_timer]
mov [es:8*4], eax
mov dword [timer_], eax
mov sp, word [start_stack]
mov bp, word [save_bp_from_timer]
;;не восстановленый стек :(
sti
jmp parse_start.parse_run_only
 
 
.decode:
;input ax - число, es:di куда писать, bx=10
cmp ax, bx
jb @f
xor dx, dx
div bx
push dx
call .decode
pop ax
@@:
or al, 0x30
push ax
mov ah, 9
stosw
pop ax
ret
 
show_bl_sc_sect:
;1) отображение списка секций. Если секция не имет имя - ошибка - вывод Section unname
;проверка на наличее имени.
;входные данные es:di -указатель на секцию - cx размер секции
; push bp
mov bx, point_to_eframe
lea si, point_to_hframe
mov dx, 966
 
.home_show_fb:
cmp si, bx
jb ._show_space_fb
mov di, [si]
sub si, 2
mov cx, [si]
sub cx, di ;home first section it's end before section
call show_name_section
add dx, 160
jmp .home_show_fb
._show_space_fb:
sub dx, 4
push 0xb800
pop es
@@:
cmp dx, 0xE64
ja .exit_show_fb
mov di, dx
;clear array for message
xor ax, ax
if DEBUG
mov ax, 0x0720
end if
mov cx, 39
rep stosw
;//////////////////////
 
add dx, 160
jmp @b
.exit_show_fb:
; pop bp
ret
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/boot_st.inc
0,0 → 1,68
; Copyright (c) 2009, <Lrz>
; 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.
;*****************************************************************************
 
;======================================================================
;
; BOOT DATA
;
;======================================================================
 
 
version db 'Secondary Loader v 0.010',0
version_end:
 
select_section db 'Select section:'
select_section_end:
section_description db 'Section description:'
section_description_end:
soft_mes db 'Soft (c) 2008-2009'
soft_mes_end:
 
badprocessor db '>Fatal - CPU 586+ required.',0
error_ini_f1 db '>Error: cannot load ini file, buffer is full',0
error_ini_f2 db '>Error: ini file not found',0
error_ini_f3 db '>Error: cannot read ini file',0
error_ini_nf db '>Error: unrecognized error when loading ini file',0
not_found_sec_loader db '>Not found section [loader]',0
not_found_def_sect db '>Not found value default in section [loader]',0
default_eq_loader db '>Error in section [loader] parametr default=loader',0
found_equal_default db '>Found equal parametr default will be use first value',0
found_equal_timeout db '>Found equal parametr timeout will be use first value',0
set_default_timeout_val db '>Section timeout has incorrect value, will be use default value',0
error_ini_common db ">I will use predefined settings and try to boot. Let's hope for the best..."
db 13,10,"Press any key to continue...",0
load_ini db '>Ini file loaded successfully',0
parse_ini_end db '>End parsing ini file',0
point_to_default_sec_not_found db '>Point to default section is not found in ini file',0
incorect_section_define db ">Incorect section define not found ']'",0
default_section_name db '"Section unname"'
 
start_msg db "Press any key to change default section, press [Enter] to continue booting"
start_msg_e:
time_msg db "or wait 4 seconds before default continuation"
time_msg_e:
time_str db "seconds before default continuation"
time_str_e:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/listing.inc
0,0 → 1,635
; Listing generator
; LocoDelAssembly 2007.06.01
 
INSTRUCTIONS equ bt in ja jb jc je jg jl jo jp js jz or \
aaa aad aam aas adc add and bsf bsr btc btr bts cbw cdq clc \
cld cli cmc cmp cqo cwd daa das dec div fld fst hlt inc ins \
int jae jbe jge jle jmp jna jnb jnc jne jng jnl jno jnp jns \
jnz jpe jpo lar lds lea les lfs lgs lsl lss ltr mov mul neg \
nop not out pop por rcl rcr ret rol ror rsm sal sar sbb shl \
shr stc std sti str sub ud2 xor \
arpl call cdqe clgi clts cmps cwde emms fabs fadd fbld fchs \
fcom fcos fdiv feni fild fist fld1 fldz fmul fnop fsin fstp \
fsub ftst fxam fxch idiv imul insb insd insw int1 int3 into \
invd iret jcxz jnae jnbe jnge jnle lahf lgdt lidt lldt lmsw \
lods loop movd movq movs orpd orps outs pand popa popd popf \
popq popw push pxor retd retf retn retq retw sahf salc scas \
seta setb setc sete setg setl seto setp sets setz sgdt shld \
shrd sidt sldt smsw stgi stos test verr verw wait xadd xchg \
xlat \
addpd addps addsd addss andpd andps bound bswap cmova cmovb \
cmovc cmove cmovg cmovl cmovo cmovp cmovs cmovz cmppd cmpps \
cmpsb cmpsd cmpsq cmpss cmpsw cpuid divpd divps divsd divss \
enter f2xm1 faddp fbstp fclex fcomi fcomp fdisi fdivp fdivr \
femms ffree fiadd ficom fidiv fimul finit fistp fisub fldcw \
fldpi fmulp fneni fprem fptan fsave fsqrt fstcw fstsw fsubp \
fsubr fucom fwait fyl2x icebp iretd iretq iretw jecxz jrcxz \
lddqu leave lodsb lodsd lodsq lodsw loopd loope loopq loopw \
loopz maxpd maxps maxsd maxss minpd minps minsd minss movsb \
movsd movsq movss movsw movsx movzx mulpd mulps mulsd mulss \
mwait outsb outsd outsw pabsb pabsd pabsw paddb paddd paddq \
paddw pandn pause pavgb pavgw pf2id pf2iw pfacc pfadd pfmax \
pfmin pfmul pfrcp pfsub pi2fd pi2fw popad popaw popfd popfq \
popfw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb \
psubd psubq psubw pusha pushd pushf pushq pushw rcpps rcpss \
rdmsr rdpmc rdtsc retfd retfq retfw retnd retnq retnw scasb \
scasd scasq scasw setae setbe setge setle setna setnb setnc \
setne setng setnl setno setnp setns setnz setpe setpo stosb \
stosd stosq stosw subpd subps subsd subss vmrun vmxon wrmsr \
xlatb xorpd xorps \
andnpd andnps cmovae cmovbe cmovge cmovle cmovna cmovnb cmovnc\
cmovne cmovng cmovnl cmovno cmovnp cmovns cmovnz cmovpe cmovpo\
comisd comiss fcmovb fcmove fcmovu fcomip fcompp fdivrp ffreep\
ficomp fidivr fisttp fisubr fldenv fldl2e fldl2t fldlg2 fldln2\
fnclex fndisi fninit fnsave fnstcw fnstsw fpatan fprem1 frstor\
frstpm fscale fsetpm fstenv fsubrp fucomi fucomp fxsave haddpd\
haddps hsubpd hsubps invlpg lfence looped loopeq loopew loopne\
loopnz loopzd loopzq loopzw mfence movapd movaps movdqa movdqu\
movhpd movhps movlpd movlps movnti movntq movsxd movupd movups\
paddsb paddsw pextrw pfnacc pfsubr phaddd phaddw phsubd phsubw\
pinsrw pmaxsw pmaxub pminsw pminub pmulhw pmullw psadbw pshufb\
pshufd pshufw psignb psignd psignw pslldq psrldq psubsb psubsw\
pswapd pushad pushaw pushfd pushfq pushfw rdmsrq rdtscp setalc\
setnae setnbe setnge setnle sfence shufpd shufps skinit sqrtpd\
sqrtps sqrtsd sqrtss swapgs sysret vmcall vmload vmread vmsave\
vmxoff wbinvd wrmsrq \
clflush cmovnae cmovnbe cmovnge cmovnle cmpeqpd cmpeqps \
cmpeqsd cmpeqss cmplepd cmpleps cmplesd cmpless cmpltpd \
cmpltps cmpltsd cmpltss cmpxchg fcmovbe fcmovnb fcmovne \
fcmovnu fdecstp fincstp fnstenv frndint fsincos fucomip \
fucompp fxrstor fxtract fyl2xp1 invlpga ldmxcsr loopned \
loopneq loopnew loopnzd loopnzq loopnzw monitor movddup \
movdq2q movhlps movlhps movntdq movntpd movntps movq2dq \
paddusb paddusw palignr pavgusb pcmpeqb pcmpeqd pcmpeqw \
pcmpgtb pcmpgtd pcmpgtw pfcmpeq pfcmpge pfcmpgt pfpnacc \
pfrsqrt phaddsw phsubsw pmaddwd pmulhrw pmulhuw pmuludq \
pshufhw pshuflw psubusb psubusw rsqrtps rsqrtss stmxcsr \
syscall sysexit sysretq ucomisd ucomiss vmclear vmmcall \
vmptrld vmptrst vmwrite \
addsubpd addsubps cmpneqpd cmpneqps cmpneqsd cmpneqss cmpnlepd\
cmpnleps cmpnlesd cmpnless cmpnltpd cmpnltps cmpnltsd cmpnltss\
cmpordpd cmpordps cmpordsd cmpordss cvtdq2pd cvtdq2ps cvtpd2dq\
cvtpd2pi cvtpd2ps cvtpi2pd cvtpi2ps cvtps2dq cvtps2pd cvtps2pi\
cvtsd2si cvtsd2ss cvtsi2sd cvtsi2ss cvtss2sd cvtss2si fcmovnbe\
maskmovq movmskpd movmskps movshdup movsldup packssdw packsswb\
packuswb pfrcpit1 pfrcpit2 pfrsqit1 pmovmskb pmulhrsw prefetch\
sysenter sysexitq unpckhpd unpckhps unpcklpd unpcklps vmlaunch\
vmresume \
cmpxchg8b cvttpd2dq cvttpd2pi cvttps2dq cvttps2pi cvttsd2si \
cvttss2si pmaddubsw prefetchw punpckhbw punpckhdq punpckhwd \
punpcklbw punpckldq punpcklwd \
cmpunordpd cmpunordps cmpunordsd cmpunordss cmpxchg16b \
loadall286 loadall386 maskmovdqu prefetcht0 prefetcht1 \
prefetcht2 punpckhqdq punpcklqdq prefetchnta
 
PREFIXES equ rep lock repe repz repne repnz
 
DATA_DEFINITORS equ db dw du dd dp df dq dt file
DATA_RESERVERS equ rb rw rd rp rf rq rt
 
CRLF equ 13, 10 ; Remove 13 for Linux
MAX_BYTES equ 13
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MODE MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
macro use16
{
use16
_USE = 16
}
 
macro use32
{
use32
_USE = 32
}
 
macro use64
{
use64
_USE = 64
}
 
macro detect_mode
{
local aux
 
_USE = 32
 
virtual at 0
xchg eax, eax
load aux byte from 0
 
if aux = $66
_USE = 16
else if aux = $87
_USE = 64
end if
end virtual
}
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;; DISPLAYING MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
macro display_address address*
{
local aux, digit
 
aux = address
 
repeat _USE / 4
digit = aux shr (_USE - 4 * %) and $F
 
display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F
end repeat
 
display ': '
}
 
macro display_bytes pointer
{
local aux, size, digit
 
size = $ - pointer
 
if size > MAX_BYTES
size = MAX_BYTES
end if
 
repeat size
load aux byte from pointer+%-1
 
digit = aux shr 4
display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F
 
digit = aux and $F
display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F
 
 
display ' '
end repeat
 
repeat MAX_BYTES - size
display ' '
end repeat
}
 
; The macro below in some situations doesn't adds a space to separate things unfortunatelly, so for readability ensurance
; another one will be used instead...
;macro display_args [args]
;{
;common
; aux = 1
;
;forward
; if ~args eq
; if aux
; display ' '
; else
; display ', '
; end if
;
; aux = 0
;
; match =ON, _RESOLVE_EQUATES
; \{
; match args, args
; \\{
; irps arg, args
; \\\{
; display \\\`arg
; \\\}
; \\}
; \}
; match =OFF, _RESOLVE_EQUATES
; \{
; irps arg, args
; \\{
; display \\`arg
; \\}
;
; \}
; end if
;}
 
; This one separates everything with one space. A very ugly listing but at least you will not see things
; like "push ebxesiedi" nor "ret word0"
 
macro display_args [args]
{
common
aux = 1
 
forward
if ~args eq
if ~aux
display ','
end if
 
aux = 0
 
match =ON, _RESOLVE_EQUATES
\{
match args, args
\\{
if ~args eqtype ""
irps arg, args
\\\{
display ' ', \\\`arg
\\\}
else
display " '", args, "'"
end if
\\}
\}
match =OFF, _RESOLVE_EQUATES
\{
if ~args eqtype ""
irps arg, args
\\{
display ' ', \\`arg
\\}
else
display " '", args, "'"
end if
\}
end if
}
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;; INSTRUCTIONS & PREFIXES MACROSES ;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
macro prefix mnemonic
{
local aux
 
macro mnemonic [args]
\{
\common
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\}
match =equ, args\\{_LISTING equ 0\\}
match =equ any, args\\{_LISTING equ 0\\}
 
match =1, _LISTING
\\{
display_address $
aux = $
\\}
 
mnemonic
 
match =1, _LISTING
\\{
display_bytes aux
 
display \`mnemonic
display CRLF
\\}
 
match =1, _ON_VIRTUAL\\{restore _LISTING\\}
match =equ, args\\{restore _LISTING\\}
match =equ any, args\\{restore _LISTING\\}
 
def_prefix mnemonic
args
purge mnemonic
\}
}
 
macro def_prefix mnemonic
{
macro def_prefix mnemonic
\{
prefix mnemonic
\}
def_prefix mnemonic
}
 
macro instruction mnemonic
{
local aux
 
macro mnemonic [args]
\{
\common
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\}
match =equ, args\\{_LISTING equ 0\\}
match =equ any, args\\{_LISTING equ 0\\}
 
match =1, _LISTING
\\{
display_address $
aux = $
\\}
 
mnemonic args
 
match =1, _LISTING
\\{
display_bytes aux
 
display \`mnemonic
 
virtual at 0
db \`mnemonic
repeat 11 - $
display ' '
end repeat
end virtual
 
display_args args
display CRLF
\\}
 
match =1, _ON_VIRTUAL\\{restore _LISTING\\}
match =equ, args\\{restore _LISTING\\}
match =equ any, args\\{restore _LISTING\\}
\}
}
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
macro data_define mnemonic
{
local aux
macro mnemonic [args]
\{
\common
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\}
match =equ, args\\{_LISTING equ 0\\}
match =equ any, args\\{_LISTING equ 0\\}
 
match =1, _LISTING
\\{
display_address $
aux = $
\\}
 
mnemonic args
 
match =1, _LISTING
\\{
display_bytes aux
 
display \`mnemonic
 
display_args args
display CRLF
 
aux = aux + MAX_BYTES
 
repeat ($ - aux + MAX_BYTES - 1) / MAX_BYTES
display_address aux
display_bytes aux
display CRLF
 
aux = aux + MAX_BYTES
end repeat
\\}
 
match =1, _ON_VIRTUAL\\{restore _LISTING\\}
match =equ, args\\{restore _LISTING\\}
match =equ any, args\\{restore _LISTING\\}
\}
 
struc mnemonic [args]
\{
\common
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\}
match =equ, args\\{_LISTING equ 0\\}
match =equ any, args\\{_LISTING equ 0\\}
 
match =1, _LISTING
\\{
display_address $
aux = $
\\}
 
. mnemonic args
 
match =1, _LISTING
\\{
display_bytes aux
 
display \`., ' ', \`mnemonic
 
display_args args
display CRLF
 
aux = aux + MAX_BYTES
 
repeat ($ - aux + MAX_BYTES - 1) / MAX_BYTES
display_address aux
display_bytes aux
display CRLF
 
aux = aux + MAX_BYTES
end repeat
\\}
 
match =1, _ON_VIRTUAL\\{restore _LISTING\\}
match =equ, args\\{restore _LISTING\\}
match =equ any, args\\{restore _LISTING\\}
\}
}
 
macro data_reserve mnemonic
{
local aux
macro mnemonic [args]
\{
\common
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\}
match =equ, args\\{_LISTING equ 0\\}
match =equ any, args\\{_LISTING equ 0\\}
 
match =1, _LISTING
\\{
display_address $
aux = $
\\}
 
mnemonic args
 
match =1, _LISTING
\\{
times MAX_BYTES display ' '
 
display \`mnemonic
 
display_args args
display CRLF
\\}
 
match =1, _ON_VIRTUAL\\{restore _LISTING\\}
match =equ, args\\{restore _LISTING\\}
match =equ any, args\\{restore _LISTING\\}
\}
 
struc mnemonic [args]
\{
\common
match =1, _ON_VIRTUAL\\{_LISTING equ 0\\}
match =equ, args\\{_LISTING equ 0\\}
match =equ any, args\\{_LISTING equ 0\\}
 
match =1, _LISTING
\\{
display_address $
aux = $
\\}
 
. mnemonic args
 
match =1, _LISTING
\\{
times MAX_BYTES display ' '
 
display \`., ' ', \`mnemonic
 
display_args args
display CRLF
\\}
 
match =1, _ON_VIRTUAL\\{restore _LISTING\\}
match =equ, args\\{restore _LISTING\\}
match =equ any, args\\{restore _LISTING\\}
\}
}
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;; LISTING CONTROL MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
macro virtual [args]
{
common
_ON_VIRTUAL equ 1
 
virtual args
}
 
macro end [args]
{
common
match =virtual, args\{restore _ON_VIRTUAL\}
 
end args
}
 
macro enable_listing
{
detect_mode
 
match =0, _MACROSES_INSTALLED
\{
match instructions, INSTRUCTIONS
\\{
irps ins, instructions
\\\{
instruction ins
\\\}
\\}
 
match prefixes, PREFIXES
\\{
irps prefix, prefixes
\\\{
def_prefix prefix
\\\}
\\}
 
match data_definitors, DATA_DEFINITORS
\\{
irps def, data_definitors
\\\{
data_define def
\\\}
\\}
 
match data_reservers, DATA_RESERVERS
\\{
irps def, data_reservers
\\\{
data_reserve def
\\\}
\\}
\}
 
_MACROSES_INSTALLED equ 1
_LISTING equ 1
}
 
macro disable_listing
{
_LISTING equ 0
}
 
macro enable [feature*]
{
forward
UNKNOWN equ 1
 
match =resolve_equates, feature
\{
restore _RESOLVE_EQUATES
_RESOLVE_EQUATES equ ON
UNKNOWN equ 0
\}
 
match =listing, feature
\{
enable_listing
UNKNOWN equ 0
\}
 
match =1, UNKNOWN
\{
display 'ERROR: Unknown "',`feature, '" feature', 13, 10
err
\}
 
restore UNKNOWN
restore UNKNOWN
}
 
macro disable [feature*]
{
UNKNOWN equ 1
 
match =resolve_equates, feature
\{
restore _RESOLVE_EQUATES
_RESOLVE_EQUATES equ OFF
UNKNOWN equ 0
\}
 
match =listing, feature
\{
disable_listing
UNKNOWN equ 0
\}
 
match =1, UNKNOWN
\{
display 'ERROR: Unknown "',`feature, '" feature', 13, 10
err
\}
 
restore UNKNOWN
restore UNKNOWN
}
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INITIALIZATION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
_MACROSES_INSTALLED equ 0
_ON_VIRTUAL equ 0
 
disable resolve_equates
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/trunk/build_ru.bat
0,0 → 1,4
@fasm -m 65535 loader.asm loader
@echo off
REM @fasm -m 65535 loader.asm loader > loader.lst
REM @pause
/kernel/branches/kolibri-ahci/sec_loader/trunk
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/kernel/branches/kolibri-ahci/sec_loader/.
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property