acpi: merge trunk

git-svn-id: svn://kolibrios.org@2465 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2012-03-15 12:41:29 +00:00
parent 272e29533c
commit c3da687125
160 changed files with 7579 additions and 355 deletions

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2011-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2011-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; RAMDISK functions ;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Shutdown for Menuet ;;

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FAT12 boot sector for Kolibri OS
;
; Copyright (C) Alex Nogueira Teixeira

View File

@ -0,0 +1,2 @@
@fasm -m 65535 kordldr.win.asm kordldr.win
@pause

View File

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

View File

@ -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 'kernel.mnt',0
align 4
dat:
extended_part_start dd 0 ; start sector for main extended partition
extended_part_cur dd ? ; start sector for current extended child
extended_parent dd 0 ; start sector for current extended parent
partition_start dd 0 ; start sector for current logical disk
cur_partition_ofs dw ? ; offset in MBR data for current partition
sect_per_clust dd 0
; change this variable if you want to boot from other physical drive
boot_drive db 80h
in_callback db 0
; uninitialized data
use_lba db ?
cur_chunk_resident db ?
align 2
heads dw ?
sectors dw ?
cache1head rw 2
cache1end dw ?
cache1limit dw ?
data_start dd ?
cachelimit dw ?
load_file_ptr dw ?
cur_obj dw ?
missing_slash dw ?
root_clus dd ?
root_start dd ?
get_next_cluster_ptr dw ?
frs_size dw ?
freeattr dw ?
index_root dw ?
index_alloc dw ?
cur_index_seg dw ?
cur_index_cache dw ?
filesize dd ?
filesize_sectors dd ?
cur_cluster dd ?
cur_delta dd ?
num_sectors dd ?
sectors_read dd ?
cur_chunk_ptr dw ?
rootcache_size dw ? ; must be immediately before foldcache_clus
if $-dat >= 0x80
warning:
unoptimal data displacement!
end if
foldcache_clus rd 7
foldcache_mark rw 7
foldcache_size rw 7
fat_filename rb 11
if $ > 2000h
error:
file is too big
end if
; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long
repeat 0x2600 - $
db 2 ; any data can be here; 2 is another nice face in ASCII :)
end repeat

View File

@ -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. Добавляет сектор в конец списка (самый новый вход).

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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. Если же нет, то считываются все сектора, кроме последнего, после чего
последний сектор считывается отдельно во временную область, и уже
оттуда нужная часть данных копируется в буфер.

View File

@ -0,0 +1,2 @@
@fasm -m 65535 bootsect.asm bootsect.bin
@pause

View File

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

View File

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

View File

@ -0,0 +1,3 @@
@fasm -m 65535 bootsect.asm bootsect.bin
@fasm -m 65535 kordldr.f1x.asm kordldr.f1x
@pause

View File

@ -0,0 +1,689 @@
; Copyright (c) 2008-2009, diamond
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the <organization> nor the
; names of its contributors may be used to endorse or promote products
; derived from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;*****************************************************************************
org 0x7E00
; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here
; ss:bp = 0:7C00
virtual at bp
rb 3 ; BS_jmpBoot
rb 8 ; BS_OEMName, ignored
dw ? ; BPB_BytsPerSec
BPB_SecsPerClus db ?
BPB_RsvdSecCnt dw ?
BPB_NumFATs db ?
BPB_RootEntCnt dw ?
BPB_TotSec16 dw ?
db ? ; BPB_Media
BPB_FATSz16 dw ?
BPB_SecPerTrk dw ?
BPB_NumHeads dw ?
BPB_HiddSec dd ?
BPB_TotSec32 dd ?
BS_DrvNum db ?
fat_type db ? ; this is BS_Reserved1,
; we use it to save FS type: 0=FAT12, 1=FAT16
db ? ; BS_BootSig
num_sectors dd ? ; BS_VolID
; rb 11 ; BS_VolLab
; rb 3 ; BS_FilSysType, first 3 bytes
read_sectors dw ?
read_sectors2 dw ?
lookup_in_root_dir dw ?
scan_for_filename dw ?
err_ dw ?
noloader dw ?
cachelimit dw ?
filesize: ; will be used to save file size
rb 5 ; BS_FilSysType, last 5 bytes
; following variables are located in the place of starting code;
; starting code is no more used at this point
sect_per_clus dw ?
cur_cluster dw ?
next_cluster dw ?
flags dw ?
cur_delta dd ?
end virtual
; procedures from boot sector
; LBA version
lba_read_sectors = 7CE2h
lba_read_sectors2 = 7CDCh
lba_lookup_in_root_dir = 7D4Fh
lba_scan_for_filename = 7D2Dh
lba_err = 7CB5h
lba_noloader = 7CB2h
; CHS version
chs_read_sectors = 7CDEh
chs_read_sectors2 = 7CD8h
chs_lookup_in_root_dir = 7D70h
chs_scan_for_filename = 7D4Eh
chs_err = 7CB1h
chs_noloader = 7CAEh
push ax cx ; save our position on disk
push ss
pop es
; determine version of bootsector (LBA vs CHS)
; mov [read_sectors], chs_read_sectors
; mov [read_sectors2], chs_read_sectors2
; mov [lookup_in_root_dir], chs_lookup_in_root_dir
; mov [scan_for_filename], chs_scan_for_filename
; mov [err], chs_err
; mov [noloader], chs_noloader
lea di, [read_sectors]
mov si, chs_proc_addresses
mov cx, 6*2
cmp word [chs_scan_for_filename], 0xFF31 ; 'xor di,di'
jz @f
add si, cx
; mov [read_sectors], lba_read_sectors
; mov [read_sectors2], lba_read_sectors2
; mov [lookup_in_root_dir], lba_lookup_in_root_dir
; mov [scan_for_filename], lba_scan_for_filename
; mov [err], lba_err
; mov [noloader], lba_noloader
@@:
rep movsb
mov cl, [BPB_SecsPerClus]
mov [sect_per_clus], cx
xor bx, bx
; determine size of cache for folders
int 12h ; ax = size of available base memory in Kb
sub ax, 94000h / 1024
jae @f
nomem:
mov si, nomem_str
jmp [err_]
@@:
shr ax, 3
mov [cachelimit], ax ; size of cache - 1
; get type of file system - FAT12 or FAT16?
; calculate number of clusters
mov ax, [BPB_TotSec16]
xor dx, dx
test ax, ax
jnz @f
mov ax, word [BPB_TotSec32]
mov dx, word [BPB_TotSec32+2]
@@:
sub ax, [bp-8] ; dword [bp-8] = first data sector
sbb dx, [bp-6]
jb j_noloader
div [sect_per_clus]
; ax = number of clusters
; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes
mov [fat_type], ch
cmp ax, 0xFF5
jb init_fat12
inc [fat_type]
init_fat16:
; no sectors loaded
mov di, 0x8200
xor ax, ax
mov cx, 0x100/2
rep stosw
jmp init_fat_done
init_fat12:
; read FAT
push 0x6000
pop es
mov ax, [BPB_RsvdSecCnt]
mov cx, [BPB_FATSz16]
cmp cx, 12
jb @f
mov cx, 12
@@:
xor dx, dx
call [read_sectors]
init_fat_done:
; if cluster = sector, we need to read second part of our file
; (bootsector loads only first cluster of kordldr.f1x)
pop cx ax ; restore our position on disk
cmp cx, 1
ja kordldr_full
sub ax, [bp-8]
inc ax
inc ax ; ax = first cluster of kordldr.f12
call get_next_cluster
jc @f
j_noloader:
jmp [noloader]
@@:
dec ax
dec ax
push 0x800
pop es
call [read_sectors2]
kordldr_full:
; ...continue loading...
mov di, secondary_loader_info
call load_file
test bx, bx
mov bx, [err_]
jz @f
mov si, aKernelNotFound
jmp bx
@@:
; for subsequent calls to callback function, hook error handler
; mov byte [bx], 0xE9 ; 'jmp' opcode
; mov ax, hooked_err - 3
; sub ax, bx
; mov word [bx+1], ax
; push hooked_err / ret
mov word [bx], 0x68 + ((hooked_err and 0xFF) shl 8)
mov word [bx+2], (hooked_err shr 8) + (0xC3 shl 8)
; set registers for secondary loader
mov ah, [BS_DrvNum]
mov al, 'f'
test ah, ah
jns @f
sub ah, 80h
mov al, 'h'
@@:
mov bx, '12'
cmp [fat_type], 0
jz @f
mov bh, '6'
@@:
mov si, callback ; ds:si = far pointer to callback procedure
jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000
nomem_str db 'No memory',0
chs_proc_addresses:
dw chs_read_sectors
dw chs_read_sectors2
dw chs_lookup_in_root_dir
dw chs_scan_for_filename
dw chs_err
dw chs_noloader
lba_proc_addresses:
dw lba_read_sectors
dw lba_read_sectors2
dw lba_lookup_in_root_dir
dw lba_scan_for_filename
dw lba_err
dw lba_noloader
get_next_cluster:
; in: ax = cluster
; out: if there is next cluster: CF=1, ax = next cluster
; out: if there is no next cluster: CF=0
push si
cmp [fat_type], 0
jnz gnc16
; for FAT12
push ds
push 0x6000
pop ds
mov si, ax
shr si, 1
add si, ax
test al, 1
lodsw
jz @f
shr ax, 4
@@:
and ax, 0xFFF
cmp ax, 0xFF7
pop ds si
ret
; for FAT16
gnc16:
; each sector contains 200h bytes = 100h FAT entries
; so ah = # of sector, al = offset in sector
mov si, ax
mov ah, 0
shr si, 8
; calculate segment for this sector of FAT table
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si)
; segment = 6000 + 20*si, offset = 0
push es
push si
shl si, 5
add si, 0x6000
mov es, si
pop si
cmp byte [ss:0x8200+si], ah ; sector already loaded?
jnz @f
; load corresponding sector
pusha
push es
xor bx, bx
mov ax, [BPB_RsvdSecCnt]
xor dx, dx
add ax, si
adc dx, bx
mov cx, 1 ; read 1 sector
call [read_sectors]
pop es
popa
@@:
mov si, ax
add si, si
; mov ax, [es:si]
lods word [es:si]
pop es
cmp ax, 0xFFF7
pop si
ret
if $ > 0x8000
error 'get_next_cluster must fit in first sector of kordldr.f1x!'
end if
load_file:
; in: ss:bp = 0:7C00
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; ASCIIZ name
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found
; out: dx:ax = file size (0xFFFFFFFF if file not found)
xor ax, ax ; start from root directory
mov dx, -1
mov word [filesize], dx
mov word [filesize+2], dx ; initialize file size with invalid value
lea si, [di+6]
parse_dir_loop:
; convert name to FAT name
push di
push ax
push ss
pop es
; convert ASCIIZ filename to FAT name
mov di, filename
push di
mov cx, 8+3
mov al, ' '
rep stosb
pop di
mov cl, 8 ; 8 symbols per name
mov bl, 1
nameloop:
lodsb
test al, al
jz namedone
cmp al, '/'
jz namedone
cmp al, '.'
jz namedot
dec cx
js badname
cmp al, 'a'
jb @f
cmp al, 'z'
ja @f
sub al, 'a'-'A'
@@:
stosb
jmp nameloop
namedot:
inc bx
jp badname
add di, cx
mov cl, 3
jmp nameloop
badname: ; do not make direct js/jp to notfound_pop:
; this generates long forms of conditional jumps and results in longer code
jmp notfound_pop
namedone:
; scan directory
pop ax ; ax = cluster of directory or 0 for root
push ds
push si
push es
pop ds
mov si, filename ; ds:si -> filename in FAT style
test ax, ax
jnz lookup_in_notroot_dir
; for root directory, use the subroutine from bootsector
call [lookup_in_root_dir]
jmp lookup_done
lookup_in_notroot_dir:
; for other directories, read a folder sector-by-sector and scan
; first, try to use the cache
push ds
push cs
pop ds
mov bx, [cachelimit]
add bx, bx
mov di, foldcache_mark
@@:
mov dx, [foldcache_clus+di-foldcache_mark+bx]
cmp dx, ax
jz cacheok
test dx, dx
jz cacheadd ; the cache has place for new entry
dec bx
dec bx
jns @b
; the folder is not present in the cache, so add it
; the cache is full; find the oldest entry and replace it with the new one
mov dx, [cachelimit]
@@:
inc bx
inc bx
cmp word [di+bx], dx ; marks have values 0 through [cachelimit]
jnz @b
cacheadd:
or word [di+bx], 0xFFFF ; very big value, it will be changed soon
mov [foldcache_clus+di-foldcache_mark+bx], ax
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet
cacheok:
; update cache marks
mov dx, [di+bx]
mov cx, [foldcache_size+di-foldcache_mark+bx]
mov di, [cachelimit]
add di, di
cacheupdate:
cmp [foldcache_mark+di], dx
adc [foldcache_mark+di], 0
dec di
dec di
jns cacheupdate
and [foldcache_mark+bx], 0
; done, bx contains (position in cache)*2
pop ds
; mov dx, bx
; shl dx, 8 ; dx = (position in cache)*0x2000/0x10
; add dx, 0x9200
lea dx, [bx+0x92]
xchg dl, dh
mov es, dx
jcxz not_in_cache
call [scan_for_filename]
jz lookup_done
not_in_cache:
; cache miss, read folder data from disk
mov bx, cx
shr bx, 4
shl cx, 5
mov di, cx ; es:di -> free space in cache entry
; external loop: scan clusters
folder_next_cluster:
; internal loop: scan sectors in cluster
mov cx, [sect_per_clus]
push ax
dec ax
dec ax
mul cx
add ax, [bp-8]
adc dx, [bp-6] ; dx:ax = absolute sector
folder_next_sector:
; skip first bx sectors
dec bx
jns folder_skip_sector
push cx
push es di
push 0x8000
pop es
xor bx, bx
mov cx, 1
push es
call [read_sectors]
; copy data to the cache...
pop ds
pop di es
cmp di, 0x2000 ; ...if there is free space, of course
jae @f
push si di
mov cx, 0x100
xor si, si
rep movsw
mov di, es
shr di, 8
add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache
pop di si
@@:
push es
push 0x8000
pop es
push cs
pop ds
mov cx, 0x10
call [scan_for_filename]
pop es
pop cx
jz lookup_done_pop
folder_skip_sector:
inc ax
jnz @f
inc dx
@@:
loop folder_next_sector
pop ax ; ax = current cluster
call get_next_cluster
jc folder_next_cluster
stc
push ax
lookup_done_pop:
pop ax
lookup_done:
pop si
pop ds
; CF=1 <=> failed
jnc found
notfound:
pop di
mov bx, 2 ; file not found
mov ax, 0xFFFF
mov dx, ax ; invalid file size
ret
notfound_pop:
pop ax
jmp notfound
found:
mov ax, [es:di+26] ; get cluster
test byte [es:di+11], 10h ; directory?
jz regular_file
cmp byte [si-1], 0
jz notfound ; don't read directories as a regular files
; ok, we have found a directory and the caller requested a file into it
pop di
jmp parse_dir_loop ; restart with new cluster in ax
regular_file:
cmp byte [si-1], 0
jnz notfound ; file does not contain another files
; ok, we have found a regular file and the caller requested it
; save file size
mov dx, [es:di+28]
mov [filesize], dx
mov dx, [es:di+30]
mov [filesize+2], dx
pop di
mov si, [di+4]
shl si, 3
push si ; [ds:di+4] = limit in 4K blocks
les bx, [di] ; es:bx -> buffer
clusloop:
; ax = first cluster, top of stack contains limit in sectors
mov si, ax ; remember current cluster
xor cx, cx ; cx will contain number of consecutive clusters
mov word [cur_delta], cx
mov word [cur_delta+2], cx
mov di, ax
clusfind:
inc di
inc cx
call get_next_cluster
jnc clusread
cmp ax, di
jz clusfind
stc
clusread:
pop di ; limit in sectors
push ax ; save next cluster
pushf ; save flags
; read cx clusters, starting from si
; calculate number of sectors
xchg ax, cx
mul [sect_per_clus]
; dx:ax = number of sectors; compare with limit
mov word [num_sectors], ax
mov word [num_sectors+2], dx
jmp @f
continue_load_file:
les bx, [di] ; es:bx -> buffer
mov di, [di+4] ; ds:di = limit in 4K blocks
shl di, 3 ; now di = limit in sectors
mov ax, word [num_sectors]
mov dx, word [num_sectors+2]
mov si, [cur_cluster]
push [next_cluster]
push [flags]
or ax, dx
jz nextclus
@@:
test dx, dx
jnz clusdecrease
push dx ; limit was not exceeded
cmp ax, di
jbe @f
pop ax
clusdecrease:
push 1 ; limit was exceeded
mov ax, di
@@:
sub di, ax ; calculate new limit
sub word [num_sectors], ax
sbb word [num_sectors+2], 0
readloop:
push ax
; buffer should not cross a 64K boundary
push bx
shr bx, 4
mov cx, es
add bx, cx
neg bx
and bh, 0xF
shr bx, 5
jnz @f
mov bl, 0x80
@@:
cmp ax, bx
jbe @f
xchg ax, bx
@@:
pop bx
xchg ax, cx
; calculate starting sector
lea ax, [si-2]
mul [sect_per_clus]
add ax, word [cur_delta]
adc dx, word [cur_delta+2]
add word [cur_delta], cx
adc word [cur_delta+2], 0
; read
call [read_sectors2]
pop ax
sub ax, cx
jnz readloop
pop dx
; next cluster?
nextclus:
popf
pop ax
mov [cur_cluster], si
mov [next_cluster], ax
pushf
pop [flags]
jnc @f ; no next cluster => return
mov dl, 1 ; dh=0 in any case
test di, di
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded
push di
jmp clusloop ; all is ok, continue
hooked_err:
mov sp, 7C00h-12-2 ; restore stack
mov dx, 3 ; return: read error
@@:
mov bx, dx
mov ax, [filesize]
mov dx, [filesize+2]
ret
; Callback function for secondary loader
callback:
; in: ax = function number; only functions 1 and 2 are defined for now
; save caller's stack
mov dx, ss
mov cx, sp
; set our stack (required because we need ss=0)
xor si, si
mov ss, si
mov sp, 7C00h-8
mov bp, 7C00h
push dx
push cx
; call our function
stc ; unsupported function
dec ax
jz callback_readfile
dec ax
jnz callback_ret
; function 2: continue loading file
; can be called only after function 1 returned value bx=1 (only part of file was loaded)
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error
; out: dx:ax = file size
call continue_load_file
jmp callback_ret_succ
callback_readfile:
; function 1: read file
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; ASCIIZ name
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error
; out: dx:ax = file size (0xFFFFFFFF if file was not found)
call load_file
callback_ret_succ:
clc ; function is supported
callback_ret:
; restore caller's stack
pop cx
pop ss
mov sp, cx
; return to caller
retf
secondary_loader_info:
dw 0, 0x1000
dw 0x30000 / 0x1000
db 'kernel.mnt',0
aKernelNotFound db 'Fatal error: cannot load the kernel',0
foldcache_clus dw 0,0,0,0,0,0,0 ; start with no folders in cache
foldcache_mark rw 7
foldcache_size rw 7
filename rb 11
if $ > 0x8200
error:
table overwritten
end if

View File

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

View File

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

View File

@ -0,0 +1,3 @@
@fasm -m 65535 bootsect.asm bootsect.bin
@fasm -m 65535 kordldr.f32.asm kordldr.f32
@pause

View File

@ -0,0 +1,673 @@
; Copyright (c) 2008-2009, diamond
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the <organization> nor the
; names of its contributors may be used to endorse or promote products
; derived from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;*****************************************************************************
org 0x7E00
; the KordOS FAT32 bootsector loads first cluster of this file to 0:7E00 and transfers control to here
; ss:bp = 0:7C00
; ds = 0
virtual at bp
rb 3 ; BS_jmpBoot
rb 8 ; BS_OEMName, ignored
dw ? ; BPB_BytsPerSec
BPB_SecsPerClus db ?
BPB_RsvdSecCnt dw ?
BPB_NumFATs db ?
BPB_RootEntCnt dw ?
dw ? ; BPB_TotSec16
db ? ; BPB_Media
dw ? ; BPB_FATSz16 = 0 for FAT32
BPB_SecPerTrk dw ?
BPB_NumHeads dw ?
BPB_HiddSec dd ?
dd ? ; BPB_TotSec32
BPB_FATSz32 dd ?
BPB_ExtFlags dw ?
dw ? ; BPB_FSVer
BPB_RootClus dd ?
filesize:
dw ? ; BPB_FSInfo
dw ? ; BPB_BkBootSec
rb 12 ; BPB_Reserved
BS_DrvNum db ?
db ? ; BS_Reserved1
db ? ; BS_BootSig
dd ? ; BS_VolID
; rb 11 ; BS_VolLab
; rb 5 ; BS_FilSysType, first 5 bytes
read_sectors32 dw ?
read_sectors2 dw ?
err_ dw ?
noloader dw ?
cachelimit dw ?
fatcachehead rw 2
fatcacheend dw ?
rb 3 ; BS_FilSysType, last 3 bytes
curseg dw ?
num_sectors dd ?
cur_cluster dd ?
next_cluster dd ?
flags dw ?
cur_delta dd ?
end virtual
; procedures from boot sector
; LBA version
lba_read_sectors2 = 7CD6h
lba_err = 7CAAh
lba_noloader = 7CA7h ; = lba_err - 3
; CHS version
chs_read_sectors2 = 7CD2h
chs_err = 7CA6h
chs_noloader = 7CA3h ; = chs_err - 3
push eax cx ; save our position on disk
; determine version of bootsector (LBA vs CHS)
mov [read_sectors2], chs_read_sectors2
mov bx, chs_err
mov [err_], bx
; mov [noloader], chs_noloader
cmp byte [bx], 0xE8 ; [chs_err] = 0xE8 for CHS version, 0x14 for LBA version
jz @f
add [read_sectors2], lba_read_sectors2 - chs_read_sectors2
add [err_], lba_err - chs_err
; mov [noloader], lba_noloader
@@:
xor bx, bx
; determine size of cache for folders
int 12h ; ax = size of available base memory in Kb
sub ax, 92000h / 1024
jae @f
nomem:
mov si, nomem_str
jmp [err_]
@@:
shr ax, 3
mov [cachelimit], ax ; size of cache - 1
mov es, bx
; no folders in cache yet
mov di, foldcache_clus
mov cx, 8*4/2 + 1
xor ax, ax
rep stosw
; bootsector code caches one FAT sector, [bp-14], in 6000:0000
; initialize our (more advanced) FAT caching from this
mov di, 8400h
mov cx, di
lea si, [fatcachehead]
mov [si], si ; no sectors in cache:
mov [si+2], si ; 'prev' & 'next' links point to self
mov [fatcacheend], di ; first free item = 8400h
stosw ; 'next cached sector' link
stosw ; 'prev cached sector' link
mov eax, [bp-14]
stosd ; first sector number in cache
test eax, eax
js @f
mov [si], cx ; 'first cached sector' link = 8400h
mov [si+2], cx ; 'next cached sector' link = 8400h
mov [fatcacheend], di ; first free item = 8406h
@@:
; if cluster = sector, we need to read second part of our file
; (bootsector loads only first cluster of kordldr.f32)
pop cx eax ; restore our position on disk
cmp cx, 1
ja kordldr_full
sub eax, [bp-10]
inc eax
inc eax ; eax = first cluster of kordldr.f32
call get_next_cluster
jc @f
; jmp [noloader]
mov ax, [err_]
sub ax, 3
jmp ax
@@:
dec eax
dec eax
push 0x800
pop es
call [read_sectors2]
kordldr_full:
; bootsector code has read some data of root directory to 8000:0000
; initialize our folder caching from this
mov eax, [BPB_RootClus]
mov [foldcache_clus], eax
mov cx, [curseg]
mov ax, 8000h
sub cx, ax ; cx = size of data read in paragraphs (0x10 bytes)
shr cx, 1 ; cx = size of folder data read in entries (0x20 bytes)
mov [foldcache_size], cx
shl cx, 4
push ds
mov ds, ax
push 0x9000
pop es
xor si, si
xor di, di
rep movsw
pop ds
; ...continue loading...
mov di, secondary_loader_info
call load_file
test bx, bx
mov bx, [err_]
jz @f
mov si, aKernelNotFound
jmp bx
@@:
; for subsequent calls to callback function, hook error handler
; push hooked_err / ret
mov dword [bx], 0x68 + (hooked_err shl 8) + (0xC3 shl 24)
; set registers for secondary loader
mov ah, [bp-2] ; drive id
mov al, 'f'
btr ax, 15
jnc @f
mov al, 'h'
@@:
mov bx, '32'
mov si, callback
jmp far [si+secondary_loader_info-callback]
nomem_str db 'No memory',0
cluster2sector:
sub eax, 2
clustersz2sectorsz:
movzx ecx, [BPB_SecsPerClus]
mul ecx
ret
get_next_cluster:
; in: eax = cluster
; out: if there is next cluster: CF=1, eax = next cluster
; out: if there is no next cluster: CF=0
push di bx
push ds es
push ss
pop ds
push ss
pop es
push ax
shr eax, 7
; eax = FAT sector number; look in cache
mov di, 8400h
.cache_lookup:
cmp di, [fatcacheend]
jae .not_in_cache
scasd
scasd
jnz .cache_lookup
.in_cache:
sub di, 8
; delete this sector from the list
push si
mov si, [di]
mov bx, [di+2]
mov [si+2], bx
mov [bx], si
pop si
jmp @f
.not_in_cache:
; cache miss
; cache is full?
mov di, [fatcacheend]
cmp di, 8C00h
jnz .cache_not_full
; yes, delete the oldest entry
mov di, [fatcachehead]
mov bx, [di]
mov [fatcachehead], bx
push word [di+2]
pop word [bx+2]
jmp .cache_append
.cache_not_full:
; no, allocate new sector
add [fatcacheend], 8
.cache_append:
; read FAT
mov [di+4], eax
pushad
lea cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))] ; +0x10000 - for FASM
shl cx, 9-4-3
mov es, cx
xor bx, bx
mov cx, 1
add eax, [bp-6] ; FAT start
sub eax, [bp-10]
call [read_sectors2]
popad
@@:
; add new sector to the end of list
mov bx, di
xchg bx, [fatcachehead+2]
push word [bx]
pop word [di]
mov [bx], di
mov [di+2], bx
; get requested item
lea ax, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))]
pop di
and di, 0x7F
shl di, 2
shl ax, 9-4-3
mov ds, ax
and byte [di+3], 0x0F
mov eax, [di]
pop es ds
pop bx di
;and eax, 0x0FFFFFFF
cmp eax, 0x0FFFFFF7
ret
if $ > 0x8000
error 'get_next_cluster must fit in first sector of kordldr.f32!'
end if
load_file:
; in: ss:bp = 0:7C00
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; ASCIIZ name
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found
; out: dx:ax = file size (0xFFFFFFFF if file not found)
mov eax, [BPB_RootClus] ; start from root directory
or dword [filesize], -1 ; initialize file size with invalid value
lea si, [di+6]
parse_dir_loop:
; convert name to FAT name
push di
push ax
push ss
pop es
; convert ASCIIZ filename to FAT name
filename equ bp
mov di, filename
push di
mov cx, 8+3
mov al, ' '
rep stosb
pop di
mov cl, 8 ; 8 symbols per name
mov bl, 1
nameloop:
lodsb
test al, al
jz namedone
cmp al, '/'
jz namedone
cmp al, '.'
jz namedot
dec cx
js badname
cmp al, 'a'
jb @f
cmp al, 'z'
ja @f
sub al, 'a'-'A'
@@:
stosb
jmp nameloop
namedot:
inc bx
jp badname
add di, cx
mov cl, 3
jmp nameloop
badname: ; do not make direct js/jp to notfound_pop:
; this generates long forms of conditional jumps and results in longer code
jmp notfound_pop
namedone:
; scan directory
pop ax ; eax = cluster of directory
; high word of eax is preserved by operations above
push ds
push si
; read a folder sector-by-sector and scan
; first, try to use the cache
push ss
pop ds
mov di, foldcache_mark
xor bx, bx
mov cx, [cachelimit]
@@:
lea si, [di+bx]
mov edx, dword [foldcache_clus+si-foldcache_mark+bx]
cmp edx, eax
jz cacheok
test edx, edx
jz cacheadd ; the cache has place for new entry
inc bx
inc bx
dec cx
jns @b
; the folder is not present in the cache, so add it
; the cache is full; find the oldest entry and replace it with the new one
mov bx, -2
mov dx, [cachelimit]
@@:
inc bx
inc bx
cmp word [di+bx], dx ; marks have values 0 through [cachelimit]
jnz @b
lea si, [di+bx]
cacheadd:
or word [di+bx], 0xFFFF ; very big value, it will be changed soon
and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet
mov dword [foldcache_clus+si-foldcache_mark+bx], eax
cacheok:
; update cache marks
mov dx, [di+bx]
mov cx, [foldcache_size+di-foldcache_mark+bx]
mov di, [cachelimit]
add di, di
cacheupdate:
cmp [foldcache_mark+di], dx
adc [foldcache_mark+di], 0
dec di
dec di
jns cacheupdate
and [foldcache_mark+bx], 0
; done, bx contains (position in cache)*2
;mov dx, bx
;shl dx, 8 ; dx = (position in cache)*0x2000/0x10
;add dx, 0x9000
lea dx, [bx + 0x90]
xchg dl, dh
mov ds, dx
mov si, filename ; ss:si -> filename in FAT style
call scan_for_filename
jz lookup_done
; cache miss, read folder data from disk
mov bx, cx
shr bx, 4
shl cx, 5
mov di, cx ; es:di -> free space in cache entry
; external loop: scan clusters
folder_next_cluster:
; internal loop: scan sectors in cluster
push eax
call cluster2sector
folder_next_sector:
; skip first bx sectors
dec bx
jns folder_skip_sector
push cx
push es di
push 0x8000
pop es
xor bx, bx
mov cx, 1
push es
push eax
call [read_sectors2]
pop eax
; copy data to the cache...
pop ds
pop di es
cmp di, 0x2000 ; ...if there is free space, of course
jae @f
pusha
mov cx, 0x100
xor si, si
rep movsw
mov di, es
shr di, 8
add [ss:foldcache_size+di-0x90], 0x10 ; 0x10 new entries in the cache
popa
@@:
push es
mov cl, 0x10 ; ch=0 at this point
call scan_for_filename
pop es
pop cx
jz lookup_done_pop
folder_skip_sector:
inc eax
loop folder_next_sector
pop eax ; eax = current cluster
call get_next_cluster
jc folder_next_cluster
stc
push eax
lookup_done_pop:
pop eax
lookup_done:
pop si
; CF=1 <=> failed
jnc found
pop ds
notfound:
pop di
notfound2:
mov bx, 2 ; file not found
mov ax, 0xFFFF
mov dx, ax ; invalid file size
ret
notfound_pop:
pop ax
jmp notfound
found:
mov eax, [di+20-2]
mov edx, [di+28]
mov ax, [di+26] ; get cluster
test byte [di+11], 10h ; directory?
pop ds
pop di
jz regular_file
cmp byte [si-1], 0
jz notfound2 ; don't read directories as regular files
; ok, we have found a directory and the caller requested a file into it
jmp parse_dir_loop ; restart with new cluster in ax
regular_file:
cmp byte [si-1], 0
jnz notfound2 ; file does not contain another files
; ok, we have found a regular file and the caller requested it
; save file size
mov [filesize], edx
mov si, [di+4] ; [ds:di+4] = limit in 4K blocks
shl si, 3
push si
les bx, [di] ; es:bx -> buffer
clusloop:
; eax = first cluster, top of stack contains limit in sectors
mov esi, eax ; remember current cluster
xor ecx, ecx ; ecx will contain number of consecutive clusters
mov [cur_delta], ecx
mov edi, eax
clusfind:
inc edi
inc ecx
call get_next_cluster
jnc clusread
cmp eax, edi
jz clusfind
stc
clusread:
pop di ; limit in sectors
movzx edi, di
push eax ; save next cluster
pushf ; save flags
; read cx clusters, starting from si
; calculate number of sectors
xchg eax, ecx
call clustersz2sectorsz
mov [num_sectors], eax
jmp @f
continue_load_file:
les bx, [di] ; es:bx -> buffer
movzx edi, word [di+4] ; di = limit in 4K blocks
shl di, 3 ; now di = limit in sectors
mov eax, [num_sectors]
mov esi, [cur_cluster]
push [next_cluster]
push [flags]
test eax, eax
jz nextclus
@@:
; eax = number of sectors; compare with limit
cmp eax, edi
seta dl
push dx ; limit was exceeded?
jbe @f
mov eax, edi
@@:
sub di, ax ; calculate new limit
sub [num_sectors], eax
mov [cur_cluster], esi
; calculate starting sector
push ax
xchg eax, esi
call cluster2sector
pop cx
add eax, [cur_delta]
add [cur_delta], ecx
; read
call [read_sectors2]
pop dx
; next cluster?
nextclus:
popf
pop eax
mov [next_cluster], eax
pushf
pop [flags]
jnc @f ; no next cluster => return
mov dl, 1
test di, di
jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded
push di
jmp clusloop ; all is ok, continue
hooked_err:
mov sp, 7C00h-14-2 ; restore stack
mov dl, 3 ; return: read error
@@:
mov bl, dl
mov bh, 0
mov ax, [filesize]
mov dx, [filesize+2]
ret
scan_for_filename:
; in: ss:si -> 11-bytes FAT name
; in: ds:0 -> part of directory data
; in: cx = number of entries
; in: bh = 0
; out: if found: CF=0, ZF=1, es:di -> directory entry
; out: if not found, but continue required: CF=1 and ZF=0
; out: if not found and zero item reached: CF=1 and ZF=1
push ds
pop es
xor di, di
push cx
jcxz snoent
sloop:
cmp byte [di], bh
jz snotfound
test byte [di+11], 8 ; volume label?
jnz scont ; ignore volume labels
pusha
mov cx, 11
repz cmps byte [ss:si], byte [es:di]
popa
jz sdone
scont:
add di, 0x20
loop sloop
snoent:
inc cx ; clear ZF flag
snotfound:
stc
sdone:
pop cx
lrdret:
ret
; Callback function for secondary loader
callback:
; in: ax = function number; only functions 1 and 2 are defined for now
; save caller's stack
mov dx, ss
mov cx, sp
; set our stack (required because we need ss=0)
xor si, si
mov ss, si
mov sp, 7C00h-10
mov bp, 7C00h
push dx
push cx
; call our function
stc ; unsupported function
dec ax
jz callback_readfile
dec ax
jnz callback_ret
; function 2: continue loading file
; can be called only after function 1 returned value bx=1 (only part of file was loaded)
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error
; out: dx:ax = file size
call continue_load_file
jmp callback_ret_succ
callback_readfile:
; function 1: read file
; in: ds:di -> information structure
; dw:dw address
; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
; ASCIIZ name
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error
; out: dx:ax = file size (0xFFFFFFFF if file was not found)
call load_file
callback_ret_succ:
clc ; function is supported
callback_ret:
; restore caller's stack
pop cx
pop ss
mov sp, cx
; return to caller
retf
secondary_loader_info:
dw 0, 0x1000
dw 0x30000 / 0x1000
db 'kernel.mnt',0
aKernelNotFound db 'Fatal error: cannot load the kernel',0
;if $ > 0x8200
;error 'total size of kordldr.f32 must not exceed 1024 bytes!'
;end if
;foldcache_clus dd 0,0,0,0,0,0,0,0 ; start with no folders in cache
;foldcache_mark dw 0
; rw 7
;foldcache_size rw 8
foldcache_clus rd 8
foldcache_mark rw 8
foldcache_size rw 8

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BS_OEMName db 'KOLIBRI ' ; db 8
BPB_BytsPerSec dw 512 ; bytes per sector
BPB_SecPerClus db 1 ; sectors per cluster

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BS_OEMName db 'KOLIBRI ' ; db 8
BPB_BytsPerSec dw 512 ; bytes per sector
BPB_SecPerClus db 1 ; sectors per cluster

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BS_OEMName db 'KOLIBRI ' ; db 8
BPB_BytsPerSec dw 512 ; bytes per sector
BPB_SecPerClus db 1 ; sectors per cluster

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BS_OEMName db 'KOLIBRI ' ; db 8
BPB_BytsPerSec dw 512 ; bytes per sector
BPB_SecPerClus db 2 ; sectors per cluster

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
‡ £ΰ㧮η­λ© α¥<CEB1>β®ΰ ¤«ο <20> <20>®«¨΅ΰ¨ (FAT12, ¤¨α<C2A8>¥β )
- <20>―¨α ­¨¥

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) 2010 KolibriOS team. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2010-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; PCI16.INC ;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -521,6 +521,7 @@ struct display_t
show_cursor dd ?
move_cursor dd ?
restore_cursor dd ?
disable_mouse dd ?
mask_seqno dd ?
check_mouse dd ?
check_m_pixel dd ?

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -802,7 +802,7 @@ proc load_driver stdcall, driver_name:dword
jnz @f
cmp word [file_name+21], 'j'
jnz @f
mov esi, aSis
mov esi, aHDA
jmp .redo
@@:
xor eax, eax

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -8,7 +8,6 @@
$Revision$
align 4
proc alloc_page

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; Author: Kees J. Bot 1 Jan 1994 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Synhronization for MenuetOS. ;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2009-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Tests of malloc()/free() from the kernel heap.
; This file is not included in the kernel, it is just test application.
use32

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2007-2008. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2007-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -107,7 +107,7 @@ msg_module db 'in module ',0
msg_version db 'incompatible driver version',13,10,0
msg_www db 'please visit www.kolibrios.org',13,10,0
msg_CR db 13,10,0
aSis db 'SIS',0
aHDA db 'INTEL_HDA',0
intel_str db "GenuineIntel",0
AMD_str db "AuthenticAMD",0
@ -164,16 +164,17 @@ dll_cur_addr dd MIN_DEFAULT_DLL_ADDR
; mike.dld {
db 0
dd servetable-0x10000
draw_line dd __sys_draw_line
draw_pointer dd __sys_draw_pointer
;db 0
;dd servetable-0x10000
;align 4
;draw_line dd __sys_draw_line
;draw_pointer dd __sys_draw_pointer
;//mike.dld, 2006-08-02 [
;drawbar dd __sys_drawbar
;drawbar dd __sys_drawbar.forced
drawbar dd vesa20_drawbar
;;drawbar dd __sys_drawbar
;;drawbar dd __sys_drawbar.forced
;drawbar dd vesa20_drawbar
;//mike.dld, 2006-08-02 ]
putpixel dd __sys_putpixel
;putpixel dd __sys_putpixel
; } mike.dld
@ -398,6 +399,8 @@ hd_entries rd 1 ;unused ? 0xfe10
mouse_active rd 1
mouse_pause rd 1
redrawmouse_unconditional rd 1
img_background rd 1
mem_BACKGROUND rd 1
static_background_data rd 1

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2008. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2008-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2009. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2009-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2011-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
All functions are stdcall unless mentioned otherwise.
=== Disk ===

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; (english text below)
;------------------------------------------

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ˆ…Œ<EFBFBD>… ”“<E2809D>Šˆˆ Ž<><EFBFBD>ˆŽ<CB86><C5BD>Ž‰ ‘ˆ‘’…Œ› Kolibri 0.7.7.0
<EFBFBD>®¬¥à ä㭪樨 ¯®¬¥é ¥âáï ¢ ॣ¨áâà eax.

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SYSTEM FUNCTIONS of OS Kolibri 0.7.7.0
Number of the function is located in the register eax.

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Includes source code by Kulakov Vladimir Gennadievich. ;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2006-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -355,6 +355,7 @@ align 4
xor eax, eax
ret
align 4
.snd_gettimestamp:
cmp [edi+out_size], 8
jne .fail
@ -371,7 +372,10 @@ align 4
mov eax, esp
push ebx
push ecx
push edx
push esi
push edi
push 4 ;.out_size
@ -386,7 +390,10 @@ align 4
add esp, 6*4
pop edi
pop esi
pop edx
pop ecx
pop ebx
test eax, eax
jz @F

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2006-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2006-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,4 +1,3 @@
; Macroinstructions for defining and calling procedures
macro stdcall proc,[arg] ; directly call STDCALL procedure

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;flags------------------------------------------------------------
DEBUG equ 1 ;show messages at debug board
use_cli_sti equ 1 ;driver become more stable (theoretically)

View File

@ -1,3 +1,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;--------------------------------
; program dma
;--------------------------------

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Some files were not shown because too many files have changed in this diff Show More