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