forked from KolibriOS/kolibrios
acpi: merge trunk
git-svn-id: svn://kolibrios.org@2465 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
272e29533c
commit
c3da687125
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
|
||||||
;; Distributed under terms of the GNU General Public License ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
|
||||||
;; Distributed under terms of the GNU General Public License ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; RAMDISK functions ;;
|
;; RAMDISK functions ;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
|
||||||
;; Distributed under terms of the GNU General Public License ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; Shutdown for Menuet ;;
|
;; Shutdown for Menuet ;;
|
||||||
|
@ -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
|
; FAT12 boot sector for Kolibri OS
|
||||||
;
|
;
|
||||||
; Copyright (C) Alex Nogueira Teixeira
|
; Copyright (C) Alex Nogueira Teixeira
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
@fasm -m 65535 kordldr.win.asm kordldr.win
|
||||||
|
@pause
|
@ -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
|
@ -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
|
@ -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. Добавляет сектор в конец списка (самый новый вход).
|
@ -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
@ -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. Если же нет, то считываются все сектора, кроме последнего, после чего
|
||||||
|
последний сектор считывается отдельно во временную область, и уже
|
||||||
|
оттуда нужная часть данных копируется в буфер.
|
@ -0,0 +1,2 @@
|
|||||||
|
@fasm -m 65535 bootsect.asm bootsect.bin
|
||||||
|
@pause
|
@ -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
|
@ -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.
|
@ -0,0 +1,3 @@
|
|||||||
|
@fasm -m 65535 bootsect.asm bootsect.bin
|
||||||
|
@fasm -m 65535 kordldr.f1x.asm kordldr.f1x
|
||||||
|
@pause
|
@ -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
|
@ -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
|
@ -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.
|
@ -0,0 +1,3 @@
|
|||||||
|
@fasm -m 65535 bootsect.asm bootsect.bin
|
||||||
|
@fasm -m 65535 kordldr.f32.asm kordldr.f32
|
||||||
|
@pause
|
@ -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
|
@ -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
|
BS_OEMName db 'KOLIBRI ' ; db 8
|
||||||
BPB_BytsPerSec dw 512 ; bytes per sector
|
BPB_BytsPerSec dw 512 ; bytes per sector
|
||||||
BPB_SecPerClus db 1 ; sectors per cluster
|
BPB_SecPerClus db 1 ; sectors per cluster
|
||||||
|
@ -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
|
BS_OEMName db 'KOLIBRI ' ; db 8
|
||||||
BPB_BytsPerSec dw 512 ; bytes per sector
|
BPB_BytsPerSec dw 512 ; bytes per sector
|
||||||
BPB_SecPerClus db 1 ; sectors per cluster
|
BPB_SecPerClus db 1 ; sectors per cluster
|
||||||
|
@ -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
|
BS_OEMName db 'KOLIBRI ' ; db 8
|
||||||
BPB_BytsPerSec dw 512 ; bytes per sector
|
BPB_BytsPerSec dw 512 ; bytes per sector
|
||||||
BPB_SecPerClus db 1 ; sectors per cluster
|
BPB_SecPerClus db 1 ; sectors per cluster
|
||||||
|
@ -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
|
BS_OEMName db 'KOLIBRI ' ; db 8
|
||||||
BPB_BytsPerSec dw 512 ; bytes per sector
|
BPB_BytsPerSec dw 512 ; bytes per sector
|
||||||
BPB_SecPerClus db 2 ; sectors per cluster
|
BPB_SecPerClus db 2 ; sectors per cluster
|
||||||
|
@ -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>¥β )
|
‡ £ΰ㧮ηλ© α¥<CEB1>β®ΰ ¤«ο <20>‘ <20>®«¨΅ΰ¨ (FAT12, ¤¨α<C2A8>¥β )
|
||||||
|
|
||||||
- <20>―¨α ¨¥
|
- <20>―¨α ¨¥
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; PCI16.INC ;;
|
;; PCI16.INC ;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@ -521,6 +521,7 @@ struct display_t
|
|||||||
show_cursor dd ?
|
show_cursor dd ?
|
||||||
move_cursor dd ?
|
move_cursor dd ?
|
||||||
restore_cursor dd ?
|
restore_cursor dd ?
|
||||||
|
disable_mouse dd ?
|
||||||
mask_seqno dd ?
|
mask_seqno dd ?
|
||||||
check_mouse dd ?
|
check_mouse dd ?
|
||||||
check_m_pixel dd ?
|
check_m_pixel dd ?
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@ -802,7 +802,7 @@ proc load_driver stdcall, driver_name:dword
|
|||||||
jnz @f
|
jnz @f
|
||||||
cmp word [file_name+21], 'j'
|
cmp word [file_name+21], 'j'
|
||||||
jnz @f
|
jnz @f
|
||||||
mov esi, aSis
|
mov esi, aHDA
|
||||||
jmp .redo
|
jmp .redo
|
||||||
@@:
|
@@:
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@ -8,7 +8,6 @@
|
|||||||
$Revision$
|
$Revision$
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
proc alloc_page
|
proc alloc_page
|
||||||
|
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
|
||||||
;; Distributed under terms of the GNU General Public License ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; Author: Kees J. Bot 1 Jan 1994 ;;
|
;; Author: Kees J. Bot 1 Jan 1994 ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; Synhronization for MenuetOS. ;;
|
;; Synhronization for MenuetOS. ;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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.
|
; Tests of malloc()/free() from the kernel heap.
|
||||||
; This file is not included in the kernel, it is just test application.
|
; This file is not included in the kernel, it is just test application.
|
||||||
use32
|
use32
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; 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_version db 'incompatible driver version',13,10,0
|
||||||
msg_www db 'please visit www.kolibrios.org',13,10,0
|
msg_www db 'please visit www.kolibrios.org',13,10,0
|
||||||
msg_CR db 13,10,0
|
msg_CR db 13,10,0
|
||||||
aSis db 'SIS',0
|
aHDA db 'INTEL_HDA',0
|
||||||
|
|
||||||
intel_str db "GenuineIntel",0
|
intel_str db "GenuineIntel",0
|
||||||
AMD_str db "AuthenticAMD",0
|
AMD_str db "AuthenticAMD",0
|
||||||
@ -164,16 +164,17 @@ dll_cur_addr dd MIN_DEFAULT_DLL_ADDR
|
|||||||
|
|
||||||
|
|
||||||
; mike.dld {
|
; mike.dld {
|
||||||
db 0
|
;db 0
|
||||||
dd servetable-0x10000
|
;dd servetable-0x10000
|
||||||
draw_line dd __sys_draw_line
|
;align 4
|
||||||
draw_pointer dd __sys_draw_pointer
|
;draw_line dd __sys_draw_line
|
||||||
|
;draw_pointer dd __sys_draw_pointer
|
||||||
;//mike.dld, 2006-08-02 [
|
;//mike.dld, 2006-08-02 [
|
||||||
;drawbar dd __sys_drawbar
|
;;drawbar dd __sys_drawbar
|
||||||
;drawbar dd __sys_drawbar.forced
|
;;drawbar dd __sys_drawbar.forced
|
||||||
drawbar dd vesa20_drawbar
|
;drawbar dd vesa20_drawbar
|
||||||
;//mike.dld, 2006-08-02 ]
|
;//mike.dld, 2006-08-02 ]
|
||||||
putpixel dd __sys_putpixel
|
;putpixel dd __sys_putpixel
|
||||||
; } mike.dld
|
; } mike.dld
|
||||||
|
|
||||||
|
|
||||||
@ -398,6 +399,8 @@ hd_entries rd 1 ;unused ? 0xfe10
|
|||||||
mouse_active rd 1
|
mouse_active rd 1
|
||||||
mouse_pause rd 1
|
mouse_pause rd 1
|
||||||
|
|
||||||
|
redrawmouse_unconditional rd 1
|
||||||
|
|
||||||
img_background rd 1
|
img_background rd 1
|
||||||
mem_BACKGROUND rd 1
|
mem_BACKGROUND rd 1
|
||||||
static_background_data rd 1
|
static_background_data rd 1
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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.
|
All functions are stdcall unless mentioned otherwise.
|
||||||
|
|
||||||
=== Disk ===
|
=== Disk ===
|
||||||
|
@ -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)
|
; (english text below)
|
||||||
|
|
||||||
;------------------------------------------
|
;------------------------------------------
|
||||||
|
@ -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>›… ”“<E2809D>Š–ˆˆ Ž<>…<EFBFBD>€–ˆŽ<CB86><C5BD>Ž‰ ‘ˆ‘’…Œ› Kolibri 0.7.7.0
|
||||||
|
|
||||||
<EFBFBD>®¬¥à äãªæ¨¨ ¯®¬¥é ¥âáï ¢ ॣ¨áâà eax.
|
<EFBFBD>®¬¥à äãªæ¨¨ ¯®¬¥é ¥âáï ¢ ॣ¨áâà eax.
|
||||||
|
@ -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
|
SYSTEM FUNCTIONS of OS Kolibri 0.7.7.0
|
||||||
|
|
||||||
Number of the function is located in the register eax.
|
Number of the function is located in the register eax.
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; Includes source code by Kulakov Vladimir Gennadievich. ;;
|
;; Includes source code by Kulakov Vladimir Gennadievich. ;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@ -355,6 +355,7 @@ align 4
|
|||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
align 4
|
||||||
.snd_gettimestamp:
|
.snd_gettimestamp:
|
||||||
cmp [edi+out_size], 8
|
cmp [edi+out_size], 8
|
||||||
jne .fail
|
jne .fail
|
||||||
@ -371,7 +372,10 @@ align 4
|
|||||||
|
|
||||||
mov eax, esp
|
mov eax, esp
|
||||||
|
|
||||||
|
push ebx
|
||||||
|
push ecx
|
||||||
push edx
|
push edx
|
||||||
|
push esi
|
||||||
push edi
|
push edi
|
||||||
|
|
||||||
push 4 ;.out_size
|
push 4 ;.out_size
|
||||||
@ -386,7 +390,10 @@ align 4
|
|||||||
add esp, 6*4
|
add esp, 6*4
|
||||||
|
|
||||||
pop edi
|
pop edi
|
||||||
|
pop esi
|
||||||
pop edx
|
pop edx
|
||||||
|
pop ecx
|
||||||
|
pop ebx
|
||||||
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @F
|
jz @F
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
; Macroinstructions for defining and calling procedures
|
; Macroinstructions for defining and calling procedures
|
||||||
|
|
||||||
macro stdcall proc,[arg] ; directly call STDCALL procedure
|
macro stdcall proc,[arg] ; directly call STDCALL procedure
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ;;
|
||||||
|
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||||
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
|
;; ;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;flags------------------------------------------------------------
|
;flags------------------------------------------------------------
|
||||||
DEBUG equ 1 ;show messages at debug board
|
DEBUG equ 1 ;show messages at debug board
|
||||||
use_cli_sti equ 1 ;driver become more stable (theoretically)
|
use_cli_sti equ 1 ;driver become more stable (theoretically)
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ;;
|
||||||
|
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||||
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
|
;; ;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
; program dma
|
; program dma
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -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 ;;
|
;; 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
Loading…
Reference in New Issue
Block a user