/kernel/branches/Kolibri-acpi/fs/fs_lfn.inc |
---|
0,0 → 1,1143 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
image_of_eax EQU esp+32 |
image_of_ebx EQU esp+20 |
; System function 70 - files with long names (LFN) |
; diamond, 2006 |
iglobal |
; in this table names must be in lowercase |
rootdirs: |
db 2,'rd' |
dd fs_OnRamdisk |
dd fs_NextRamdisk |
db 7,'ramdisk' |
dd fs_OnRamdisk |
dd fs_NextRamdisk |
db 2,'fd' |
dd fs_OnFloppy |
dd fs_NextFloppy |
db 10,'floppydisk' |
dd fs_OnFloppy |
dd fs_NextFloppy |
db 3,'hd0' |
dd fs_OnHd0 |
dd fs_NextHd0 |
db 3,'hd1' |
dd fs_OnHd1 |
dd fs_NextHd1 |
db 3,'hd2' |
dd fs_OnHd2 |
dd fs_NextHd2 |
db 3,'hd3' |
dd fs_OnHd3 |
dd fs_NextHd3 |
;********************************************** |
db 3,'cd0' |
dd fs_OnCd0 |
dd fs_NextCd |
db 3,'cd1' |
dd fs_OnCd1 |
dd fs_NextCd |
db 3,'cd2' |
dd fs_OnCd2 |
dd fs_NextCd |
db 3,'cd3' |
dd fs_OnCd3 |
dd fs_NextCd |
;*********************************************** |
db 0 |
virtual_root_query: |
dd fs_HasRamdisk |
db 'rd',0 |
dd fs_HasFloppy |
db 'fd',0 |
dd fs_HasHd0 |
db 'hd0',0 |
dd fs_HasHd1 |
db 'hd1',0 |
dd fs_HasHd2 |
db 'hd2',0 |
dd fs_HasHd3 |
db 'hd3',0 |
;********************************************** |
dd fs_HasCd0 |
db 'cd0',0 |
dd fs_HasCd1 |
db 'cd1',0 |
dd fs_HasCd2 |
db 'cd2',0 |
dd fs_HasCd3 |
db 'cd3',0 |
;********************************************** |
dd 0 |
fs_additional_handlers: |
dd biosdisk_handler, biosdisk_enum_root |
; add new handlers here |
dd 0 |
endg |
file_system_lfn: |
; in: ebx->fileinfo block |
; operation codes: |
; 0 : read file |
; 1 : read folder |
; 2 : create/rewrite file |
; 3 : write/append to file |
; 4 : set end of file |
; 5 : get file/directory attributes structure |
; 6 : set file/directory attributes structure |
; 7 : start application |
; 8 : delete file |
; 9 : create directory |
; parse file name |
lea esi, [ebx+20] |
lodsb |
test al, al |
jnz @f |
mov esi, [esi] |
lodsb |
@@: |
cmp al, '/' |
jz .notcurdir |
dec esi |
mov ebp, esi |
test al, al |
jnz @f |
xor ebp, ebp |
@@: |
mov esi, [current_slot] |
mov esi, [esi+APPDATA.cur_dir] |
jmp .parse_normal |
.notcurdir: |
cmp byte [esi], 0 |
jz .rootdir |
call process_replace_file_name |
.parse_normal: |
cmp dword [ebx], 7 |
jne @F |
mov edx, [ebx+4] |
mov ebx, [ebx+8] |
call fs_execute ; esi+ebp, ebx, edx |
mov [image_of_eax], eax |
ret |
@@: |
mov edi, rootdirs-8 |
xor ecx, ecx |
push esi |
.scan1: |
pop esi |
add edi, ecx |
scasd |
scasd |
mov cl, byte [edi] |
test cl, cl |
jz .notfound_try |
inc edi |
push esi |
@@: |
lodsb |
or al, 20h |
scasb |
loopz @b |
jnz .scan1 |
lodsb |
cmp al, '/' |
jz .found1 |
test al, al |
jnz .scan1 |
pop eax |
; directory /xxx |
.maindir: |
mov esi, [edi+4] |
.maindir_noesi: |
cmp dword [ebx], 1 |
jnz .access_denied |
xor eax, eax |
mov ebp, [ebx+12] ;количество блоков для считывания |
mov edx, [ebx+16] ;куда записывать рузельтат |
; add edx, std_application_base_address |
push dword [ebx+4] ; first block |
mov ebx, [ebx+8] ; flags |
; ebx=flags, [esp]=first block, ebp=number of blocks, edx=return area, esi='Next' handler |
mov edi, edx |
push ecx |
mov ecx, 32/4 |
rep stosd |
pop ecx |
mov byte [edx], 1 ; version |
.maindir_loop: |
call esi |
jc .maindir_done |
inc dword [edx+8] |
dec dword [esp] |
jns .maindir_loop |
dec ebp |
js .maindir_loop |
inc dword [edx+4] |
mov dword [edi], 0x10 ; attributes: folder |
mov dword [edi+4], 1 ; name type: UNICODE |
push eax |
xor eax, eax |
add edi, 8 |
push ecx |
mov ecx, 40/4-2 |
rep stosd |
pop ecx |
pop eax |
push eax edx |
; convert number in eax to decimal UNICODE string |
push edi |
push ecx |
push -'0' |
mov ecx, 10 |
@@: |
xor edx, edx |
div ecx |
push edx |
test eax, eax |
jnz @b |
@@: |
pop eax |
add al, '0' |
stosb |
test bl, 1 ; UNICODE name? |
jz .ansi2 |
mov byte [edi], 0 |
inc edi |
.ansi2: |
test al, al |
jnz @b |
mov byte [edi-1], 0 |
pop ecx |
pop edi |
; UNICODE name length is 520 bytes, ANSI - 264 |
add edi, 520 |
test bl, 1 |
jnz @f |
sub edi, 520-264 |
@@: |
pop edx eax |
jmp .maindir_loop |
.maindir_done: |
pop eax |
mov ebx, [edx+4] |
xor eax, eax |
dec ebp |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
; directory / |
.rootdir: |
cmp dword [ebx], 1 ; read folder? |
jz .readroot |
.access_denied: |
mov dword [image_of_eax], 10 ; access denied |
ret |
.readroot: |
; virtual root folder - special handler |
mov esi, virtual_root_query |
mov ebp, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
push dword [ebx+4] ; first block |
mov ebx, [ebx+8] ; flags |
xor eax, eax |
; eax=0, [esp]=first block, ebx=flags, ebp=number of blocks, edx=return area |
mov edi, edx |
mov ecx, 32/4 |
rep stosd |
mov byte [edx], 1 ; version |
.readroot_loop: |
cmp dword [esi], eax |
jz .readroot_done_static |
call dword [esi] |
add esi, 4 |
test eax, eax |
jnz @f |
.readroot_next: |
or ecx, -1 |
xchg esi, edi |
repnz scasb |
xchg esi, edi |
jmp .readroot_loop |
@@: |
xor eax, eax |
inc dword [edx+8] |
dec dword [esp] |
jns .readroot_next |
dec ebp |
js .readroot_next |
inc dword [edx+4] |
mov dword [edi], 0x10 ; attributes: folder |
mov dword [edi+4], ebx ; name type: UNICODE |
add edi, 8 |
mov ecx, 40/4-2 |
rep stosd |
push edi |
@@: |
lodsb |
stosb |
test bl, 1 |
jz .ansi |
mov byte [edi], 0 |
inc edi |
.ansi: |
test eax, eax |
jnz @b |
pop edi |
add edi, 520 |
test bl, 1 |
jnz .readroot_loop |
sub edi, 520-264 |
jmp .readroot_loop |
.readroot_done_static: |
mov esi, fs_additional_handlers-8 |
sub esp, 16 |
.readroot_ah_loop: |
add esi, 8 |
cmp dword [esi], 0 |
jz .readroot_done |
xor eax, eax |
.readroot_ah_loop2: |
push edi |
lea edi, [esp+4] |
call dword [esi+4] |
pop edi |
test eax, eax |
jz .readroot_ah_loop |
inc dword [edx+8] |
dec dword [esp+16] |
jns .readroot_ah_loop2 |
dec ebp |
js .readroot_ah_loop2 |
push eax |
xor eax, eax |
inc dword [edx+4] |
mov dword [edi], 0x10 ; attributes: folder |
mov dword [edi+4], ebx |
add edi, 8 |
mov ecx, 40/4-2 |
rep stosd |
push esi edi |
lea esi, [esp+12] |
@@: |
lodsb |
stosb |
test bl, 1 |
jz .ansi3 |
mov byte [edi], 0 |
inc edi |
.ansi3: |
test al, al |
jnz @b |
pop edi esi eax |
add edi, 520 |
test bl, 1 |
jnz .readroot_ah_loop2 |
sub edi, 520-264 |
jmp .readroot_ah_loop2 |
.readroot_done: |
add esp, 16 |
pop eax |
mov ebx, [edx+4] |
xor eax, eax |
dec ebp |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.notfound_try: |
mov edi, fs_additional_handlers |
@@: |
cmp dword [edi], 0 |
jz .notfound |
call dword [edi] |
scasd |
scasd |
jmp @b |
.notfound: |
mov dword [image_of_eax], ERROR_FILE_NOT_FOUND |
and dword [image_of_ebx], 0 |
ret |
.notfounda: |
cmp edi, esp |
jnz .notfound |
add esp, 8 |
jmp .notfound |
.found1: |
pop eax |
cmp byte [esi], 0 |
jz .maindir |
.found2: |
; read partition number |
xor ecx, ecx |
xor eax, eax |
@@: |
lodsb |
cmp al, '/' |
jz .done1 |
test al, al |
jz .done1 |
sub al, '0' |
cmp al, 9 |
ja .notfounda |
lea ecx, [ecx*5] |
lea ecx, [ecx*2+eax] |
jmp @b |
.done1: |
jecxz .notfounda |
test al, al |
jnz @f |
dec esi |
@@: |
cmp byte [esi], 0 |
jnz @f |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
@@: |
; now [edi] contains handler address, ecx - partition number, |
; esi points to ASCIIZ string - rest of name |
jmp dword [edi] |
; handlers for devices |
; in: ecx = 0 => query virtual directory /xxx |
; in: ecx = partition number |
; esi -> relative (for device) name |
; ebx -> fileinfo |
; ebp = 0 or pointer to rest of name from folder addressed by esi |
; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx |
fs_OnRamdisk: |
cmp ecx, 1 |
jnz file_system_lfn.notfound |
mov eax, [ebx] |
cmp eax, fs_NumRamdiskServices |
jae .not_impl |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
add ebx, 4 |
call dword [fs_RamdiskServices + eax*4] |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.not_impl: |
mov dword [image_of_eax], 2 ; not implemented |
ret |
fs_NotImplemented: |
mov eax, 2 |
ret |
fs_RamdiskServices: |
dd fs_RamdiskRead |
dd fs_RamdiskReadFolder |
dd fs_RamdiskRewrite |
dd fs_RamdiskWrite |
dd fs_RamdiskSetFileEnd |
dd fs_RamdiskGetFileInfo |
dd fs_RamdiskSetFileInfo |
dd 0 |
dd fs_RamdiskDelete |
dd fs_RamdiskCreateFolder |
fs_NumRamdiskServices = ($ - fs_RamdiskServices)/4 |
fs_OnFloppy: |
cmp ecx, 2 |
ja file_system_lfn.notfound |
mov eax, [ebx] |
cmp eax, fs_NumFloppyServices |
jae fs_OnRamdisk.not_impl |
call reserve_flp |
mov [flp_number], cl |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
add ebx, 4 |
call dword [fs_FloppyServices + eax*4] |
and [flp_status], 0 |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
fs_FloppyServices: |
dd fs_FloppyRead |
dd fs_FloppyReadFolder |
dd fs_FloppyRewrite |
dd fs_FloppyWrite |
dd fs_FloppySetFileEnd |
dd fs_FloppyGetFileInfo |
dd fs_FloppySetFileInfo |
dd 0 |
dd fs_FloppyDelete |
dd fs_FloppyCreateFolder |
fs_NumFloppyServices = ($ - fs_FloppyServices)/4 |
fs_OnHd0: |
call reserve_hd1 |
mov [hdbase], 0x1F0 |
mov [hdid], 0 |
push 1 |
jmp fs_OnHd |
fs_OnHd1: |
call reserve_hd1 |
mov [hdbase], 0x1F0 |
mov [hdid], 0x10 |
push 2 |
jmp fs_OnHd |
fs_OnHd2: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov [hdid], 0 |
push 3 |
jmp fs_OnHd |
fs_OnHd3: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov [hdid], 0x10 |
push 4 |
fs_OnHd: |
call reserve_hd_channel |
pop eax |
mov [hdpos], eax |
cmp ecx, 0x100 |
jae fs_OnHdAndBd.nf |
cmp cl, [DRIVE_DATA+1+eax] |
fs_OnHdAndBd: |
jbe @f |
.nf: |
call free_hd_channel |
and [hd1_status], 0 |
mov dword [image_of_eax], 5 ; not found |
ret |
@@: |
mov [known_part], ecx ; mov [fat32part], ecx |
push ebx esi |
call choice_necessity_partition_1 |
pop esi ebx |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
mov eax, [ebx] |
cmp eax, fs_NumHdServices |
jae .not_impl |
add ebx, 4 |
call dword [fs_HdServices + eax*4] |
call free_hd_channel |
and [hd1_status], 0 |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.not_impl: |
call free_hd_channel |
and [hd1_status], 0 |
mov dword [image_of_eax], 2 ; not implemented |
ret |
fs_HdServices: |
dd fs_HdRead |
dd fs_HdReadFolder |
dd fs_HdRewrite |
dd fs_HdWrite |
dd fs_HdSetFileEnd |
dd fs_HdGetFileInfo |
dd fs_HdSetFileInfo |
dd 0 |
dd fs_HdDelete |
dd fs_HdCreateFolder |
fs_NumHdServices = ($ - fs_HdServices)/4 |
;******************************************************* |
fs_OnCd0: |
call reserve_cd |
mov [ChannelNumber],1 |
mov [DiskNumber],0 |
push 6 |
push 1 |
jmp fs_OnCd |
fs_OnCd1: |
call reserve_cd |
mov [ChannelNumber],1 |
mov [DiskNumber],1 |
push 4 |
push 2 |
jmp fs_OnCd |
fs_OnCd2: |
call reserve_cd |
mov [ChannelNumber],2 |
mov [DiskNumber],0 |
push 2 |
push 3 |
jmp fs_OnCd |
fs_OnCd3: |
call reserve_cd |
mov [ChannelNumber],2 |
mov [DiskNumber],1 |
push 0 |
push 4 |
fs_OnCd: |
call reserve_cd_channel |
pop eax |
mov [cdpos], eax |
pop eax |
cmp ecx, 0x100 |
jae .nf |
push ecx ebx |
mov cl,al |
mov bl,[DRIVE_DATA+1] |
shr bl,cl |
test bl,2 |
pop ebx ecx |
jnz @f |
.nf: |
call free_cd_channel |
and [cd_status], 0 |
mov dword [image_of_eax], 5 ; not found |
ret |
@@: |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
mov eax, [ebx] |
cmp eax,fs_NumCdServices |
jae .not_impl |
add ebx, 4 |
call dword [fs_CdServices + eax*4] |
call free_cd_channel |
and [cd_status], 0 |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.not_impl: |
call free_cd_channel |
and [cd_status], 0 |
mov dword [image_of_eax], 2 ; not implemented |
ret |
fs_CdServices: |
dd fs_CdRead |
dd fs_CdReadFolder |
dd fs_NotImplemented |
dd fs_NotImplemented |
dd fs_NotImplemented |
dd fs_CdGetFileInfo |
dd fs_NotImplemented |
dd 0 |
dd fs_NotImplemented |
dd fs_NotImplemented |
fs_NumCdServices = ($ - fs_CdServices)/4 |
;******************************************************* |
fs_HasRamdisk: |
mov al, 1 ; we always have ramdisk |
ret |
fs_HasFloppy: |
cmp byte [DRIVE_DATA], 0 |
setnz al |
ret |
fs_HasHd0: |
mov al, [DRIVE_DATA+1] |
and al, 11000000b |
cmp al, 01000000b |
setz al |
ret |
fs_HasHd1: |
mov al, [DRIVE_DATA+1] |
and al, 00110000b |
cmp al, 00010000b |
setz al |
ret |
fs_HasHd2: |
mov al, [DRIVE_DATA+1] |
and al, 00001100b |
cmp al, 00000100b |
setz al |
ret |
fs_HasHd3: |
mov al, [DRIVE_DATA+1] |
and al, 00000011b |
cmp al, 00000001b |
setz al |
ret |
;******************************************************* |
fs_HasCd0: |
mov al, [DRIVE_DATA+1] |
and al, 11000000b |
cmp al, 10000000b |
setz al |
ret |
fs_HasCd1: |
mov al, [DRIVE_DATA+1] |
and al, 00110000b |
cmp al, 00100000b |
setz al |
ret |
fs_HasCd2: |
mov al, [DRIVE_DATA+1] |
and al, 00001100b |
cmp al, 00001000b |
setz al |
ret |
fs_HasCd3: |
mov al, [DRIVE_DATA+1] |
and al, 00000011b |
cmp al, 00000010b |
setz al |
ret |
;******************************************************* |
; fs_NextXXX functions: |
; in: eax = partition number, from which start to scan |
; out: CF=1 => no more partitions |
; CF=0 => eax=next partition number |
fs_NextRamdisk: |
; we always have /rd/1 |
test eax, eax |
stc |
jnz @f |
mov al, 1 |
clc |
@@: |
ret |
fs_NextFloppy: |
; we have /fd/1 iff (([DRIVE_DATA] and 0xF0) != 0) and /fd/2 iff (([DRIVE_DATA] and 0x0F) != 0) |
test byte [DRIVE_DATA], 0xF0 |
jz .no1 |
test eax, eax |
jnz .no1 |
inc eax |
ret ; CF cleared |
.no1: |
test byte [DRIVE_DATA], 0x0F |
jz .no2 |
cmp al, 2 |
jae .no2 |
mov al, 2 |
clc |
ret |
.no2: |
stc |
ret |
; on hdx, we have partitions from 1 to [0x40002+x] |
fs_NextHd0: |
push 0 |
jmp fs_NextHd |
fs_NextHd1: |
push 1 |
jmp fs_NextHd |
fs_NextHd2: |
push 2 |
jmp fs_NextHd |
fs_NextHd3: |
push 3 |
fs_NextHd: |
pop ecx |
movzx ecx, byte [DRIVE_DATA+2+ecx] |
cmp eax, ecx |
jae fs_NextFloppy.no2 |
inc eax |
clc |
ret |
;******************************************************* |
fs_NextCd: |
; we always have /cdX/1 |
test eax, eax |
stc |
jnz @f |
mov al, 1 |
clc |
@@: |
ret |
;******************************************************* |
; Additional FS handlers. |
; This handler gets the control each time when fn 70 is called |
; with unknown item of root subdirectory. |
; in: esi -> name |
; ebp = 0 or rest of name relative to esi |
; out: if the handler processes path, he must not return in file_system_lfn, |
; but instead pop return address and return directly to the caller |
; otherwise simply return |
; here we test for /bd<N>/... - BIOS disks |
biosdisk_handler: |
cmp [NumBiosDisks], 0 |
jz .ret |
mov al, [esi] |
or al, 20h |
cmp al, 'b' |
jnz .ret |
mov al, [esi+1] |
or al, 20h |
cmp al, 'd' |
jnz .ret |
push esi |
inc esi |
inc esi |
cmp byte [esi], '0' |
jb .ret2 |
cmp byte [esi], '9' |
ja .ret2 |
xor edx, edx |
@@: |
lodsb |
test al, al |
jz .ok |
cmp al, '/' |
jz .ok |
sub al, '0' |
cmp al, 9 |
ja .ret2 |
lea edx, [edx*5] |
lea edx, [edx*2+eax] |
jmp @b |
.ret2: |
pop esi |
.ret: |
ret |
.ok: |
cmp al, '/' |
jz @f |
dec esi |
@@: |
add dl, 80h |
xor ecx, ecx |
@@: |
cmp dl, [BiosDisksData+ecx*4] |
jz .ok2 |
inc ecx |
cmp ecx, [NumBiosDisks] |
jb @b |
jmp .ret2 |
.ok2: |
add esp, 8 |
test al, al |
jnz @f |
mov esi, fs_BdNext |
jmp file_system_lfn.maindir_noesi |
@@: |
push ecx |
push fs_OnBd |
mov edi, esp |
jmp file_system_lfn.found2 |
fs_BdNext: |
cmp eax, [BiosDiskPartitions+ecx*4] |
inc eax |
cmc |
ret |
fs_OnBd: |
pop edx edx |
; edx = disk number, ecx = partition number |
; esi+ebp = name |
call reserve_hd1 |
add edx, 0x80 |
mov [hdpos], edx |
cmp ecx, [BiosDiskPartitions+(edx-0x80)*4] |
jmp fs_OnHdAndBd |
; This handler is called when virtual root is enumerated |
; and must return all items which can be handled by this. |
; It is called several times, first time with eax=0 |
; in: eax = 0 for first call, previously returned value for subsequent calls |
; out: eax = 0 => no more items |
; eax != 0 => buffer pointed to by edi contains name of item |
; here we enumerate existing BIOS disks /bd<N> |
biosdisk_enum_root: |
cmp eax, [NumBiosDisks] |
jae .end |
push eax |
movzx eax, byte [BiosDisksData+eax*4] |
sub al, 80h |
push eax |
mov al, 'b' |
stosb |
mov al, 'd' |
stosb |
pop eax |
cmp al, 10 |
jae .big |
add al, '0' |
stosb |
mov byte [edi], 0 |
pop eax |
inc eax |
ret |
.end: |
xor eax, eax |
ret |
.big: |
push ecx edx |
push -'0' |
mov ecx, 10 |
@@: |
xor edx, edx |
div ecx |
push edx |
test eax, eax |
jnz @b |
xchg eax, edx |
@@: |
pop eax |
add al, '0' |
stosb |
jnz @b |
pop edx ecx |
pop eax |
inc eax |
ret |
process_replace_file_name: |
mov ebp, [full_file_name_table] |
mov edi, [full_file_name_table.size] |
dec edi |
shl edi, 7 |
add edi, ebp |
.loop: |
cmp edi, ebp |
jb .notfound |
push esi edi |
@@: |
cmp byte [edi], 0 |
jz .dest_done |
lodsb |
test al, al |
jz .cont |
or al, 20h |
scasb |
jz @b |
jmp .cont |
.dest_done: |
cmp byte [esi], 0 |
jz .found |
cmp byte [esi], '/' |
jnz .cont |
inc esi |
jmp .found |
.cont: |
pop edi esi |
sub edi, 128 |
jmp .loop |
.found: |
pop edi eax |
mov ebp, esi |
cmp byte [esi], 0 |
lea esi, [edi+64] |
jnz .ret |
.notfound: |
xor ebp, ebp |
.ret: |
ret |
sys_current_directory: |
; mov esi, [current_slot] |
; mov esi, [esi+APPDATA.cur_dir] |
; mov edx, esi |
;get length string of appdata.cur_dir |
mov eax, [current_slot] |
mov edi, [eax+APPDATA.cur_dir] |
dec ebx |
jz .set |
dec ebx |
jz .get |
ret |
.get: |
; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len |
; for our code: ebx->buffer,ecx=len |
max_cur_dir equ 0x1000 |
mov ebx,edi |
push ecx |
push edi |
xor eax,eax |
mov ecx,max_cur_dir |
repne scasb ;find zerro at and string |
jnz .error ; no zero in cur_dir: internal error, should not happen |
sub edi,ebx ;lenght for copy |
inc edi |
mov [esp+32+8],edi ;return in eax |
cmp edx, edi |
jbe @f |
mov edx, edi |
@@: |
;source string |
pop esi |
;destination string |
pop edi |
cmp edx, 1 |
jbe .ret |
mov al,'/' ;start string with '/' |
stosb |
mov ecx,edx |
rep movsb ;copy string |
.ret: ret |
.error: add esp,8 |
or dword [esp+32],-1 ;error not found zerro at string ->[eax+APPDATA.cur_dir] |
ret |
.set: |
; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string |
; for our code: ebx->string to set |
; use generic resolver with APPDATA.cur_dir as destination |
push max_cur_dir ;0x1000 |
push edi ;destination |
mov ebx,ecx |
call get_full_file_name |
ret |
; in: ebx = file name, [esp+4] = destination, [esp+8] = sizeof destination |
; destroys all registers except ebp,esp |
get_full_file_name: |
push ebp |
mov esi, [current_slot] |
mov esi, [esi+APPDATA.cur_dir] |
mov edx, esi |
@@: |
inc esi |
cmp byte [esi-1], 0 |
jnz @b |
dec esi |
cmp byte [ebx], '/' |
jz .set_absolute |
; string gives relative path |
mov edi, [esp+8] ; destination |
.relative: |
cmp byte [ebx], 0 |
jz .set_ok |
cmp word [ebx], '.' |
jz .set_ok |
cmp word [ebx], './' |
jnz @f |
add ebx, 2 |
jmp .relative |
@@: |
cmp word [ebx], '..' |
jnz .doset_relative |
cmp byte [ebx+2], 0 |
jz @f |
cmp byte [ebx+2], '/' |
jnz .doset_relative |
@@: |
dec esi |
cmp byte [esi], '/' |
jnz @b |
add ebx, 3 |
jmp .relative |
.set_ok: |
cmp edx, edi ; is destination equal to APPDATA.cur_dir? |
jz .set_ok.cur_dir |
sub esi, edx |
cmp esi, [esp+12] |
jb .set_ok.copy |
.fail: |
mov byte [edi], 0 |
xor eax, eax ; fail |
pop ebp |
ret 8 |
.set_ok.copy: |
mov ecx, esi |
mov esi, edx |
rep movsb |
mov byte [edi], 0 |
.ret.ok: |
mov al, 1 ; ok |
pop ebp |
ret 8 |
.set_ok.cur_dir: |
mov byte [esi], 0 |
jmp .ret.ok |
.doset_relative: |
cmp edx, edi |
jz .doset_relative.cur_dir |
sub esi, edx |
cmp esi, [esp+12] |
jae .fail |
mov ecx, esi |
mov esi, edx |
mov edx, edi |
rep movsb |
jmp .doset_relative.copy |
.doset_relative.cur_dir: |
mov edi, esi |
.doset_relative.copy: |
add edx, [esp+12] |
mov byte [edi], '/' |
inc edi |
cmp edi, edx |
jae .overflow |
@@: |
mov al, [ebx] |
inc ebx |
stosb |
test al, al |
jz .ret.ok |
cmp edi, edx |
jb @b |
.overflow: |
dec edi |
jmp .fail |
.set_absolute: |
lea esi, [ebx+1] |
call process_replace_file_name |
mov edi, [esp+8] |
mov edx, [esp+12] |
add edx, edi |
.set_copy: |
lodsb |
stosb |
test al, al |
jz .set_part2 |
.set_copy_cont: |
cmp edi, edx |
jb .set_copy |
jmp .overflow |
.set_part2: |
mov esi, ebp |
xor ebp, ebp |
test esi, esi |
jz .ret.ok |
mov byte [edi-1], '/' |
jmp .set_copy_cont |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/fs/iso9660.inc |
---|
0,0 → 1,757 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
uglobal |
cd_current_pointer_of_input dd 0 |
cd_current_pointer_of_input_2 dd 0 |
cd_mem_location dd 0 |
cd_counter_block dd 0 |
IDE_Channel_1 db 0 |
IDE_Channel_2 db 0 |
endg |
reserve_cd: |
cli |
cmp [cd_status],0 |
je reserve_ok2 |
sti |
call change_task |
jmp reserve_cd |
reserve_ok2: |
push eax |
mov eax,[CURRENT_TASK] |
shl eax,5 |
mov eax,[eax+CURRENT_TASK+TASKDATA.pid] |
mov [cd_status],eax |
pop eax |
sti |
ret |
reserve_cd_channel: |
cmp [ChannelNumber],1 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
cli |
cmp [IDE_Channel_1],0 |
je .reserve_ok_1 |
sti |
call change_task |
jmp .IDE_Channel_1 |
.IDE_Channel_2: |
cli |
cmp [IDE_Channel_2],0 |
je .reserve_ok_2 |
sti |
call change_task |
jmp .IDE_Channel_1 |
.reserve_ok_1: |
mov [IDE_Channel_1],1 |
ret |
.reserve_ok_2: |
mov [IDE_Channel_2],1 |
ret |
free_cd_channel: |
cmp [ChannelNumber],1 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
mov [IDE_Channel_1],0 |
ret |
.IDE_Channel_2: |
mov [IDE_Channel_2],0 |
ret |
uglobal |
cd_status dd 0 |
endg |
;---------------------------------------------------------------- |
; |
; fs_CdRead - LFN variant for reading CD disk |
; |
; esi points to filename /dir1/dir2/.../dirn/file,0 |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_CdRead: |
push edi |
cmp byte [esi], 0 |
jnz @f |
.noaccess: |
pop edi |
.noaccess_2: |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
.noaccess_3: |
pop eax edx ecx edi |
jmp .noaccess_2 |
@@: |
call cd_find_lfn |
jnc .found |
pop edi |
cmp [DevErrorCode],0 |
jne .noaccess_2 |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
mov edi,[cd_current_pointer_of_input] |
test byte [edi+25],10b ; do not allow read directories |
jnz .noaccess |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
xor ebx, ebx |
.reteof: |
mov eax, 6 ; end of file |
pop edi |
ret |
@@: |
mov ebx, [ebx] |
.l1: |
push ecx edx |
push 0 |
mov eax, [edi+10] ; ðåàëüíûé ðàçìåð ôàéëîâîé ñåêöèè |
sub eax, ebx |
jb .eof |
cmp eax, ecx |
jae @f |
mov ecx, eax |
mov byte [esp], 6 |
@@: |
mov eax,[edi+2] |
mov [CDSectorAddress],eax |
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data |
.new_sector: |
test ecx, ecx |
jz .done |
sub ebx, 2048 |
jae .next |
add ebx, 2048 |
jnz .incomplete_sector |
cmp ecx, 2048 |
jb .incomplete_sector |
; we may read and memmove complete sector |
mov [CDDataBuf_pointer],edx |
call ReadCDWRetr ; ÷èòàåì ñåêòîð ôàéëà |
cmp [DevErrorCode],0 |
jne .noaccess_3 |
add edx, 2048 |
sub ecx, 2048 |
.next: |
inc dword [CDSectorAddress] |
jmp .new_sector |
.incomplete_sector: |
; we must read and memmove incomplete sector |
mov [CDDataBuf_pointer],CDDataBuf |
call ReadCDWRetr ; ÷èòàåì ñåêòîð ôàéëà |
cmp [DevErrorCode],0 |
jne .noaccess_3 |
push ecx |
add ecx, ebx |
cmp ecx, 2048 |
jbe @f |
mov ecx, 2048 |
@@: |
sub ecx, ebx |
push edi esi ecx |
mov edi,edx |
lea esi, [CDDataBuf + ebx] |
cld |
rep movsb |
pop ecx esi edi |
add edx, ecx |
sub [esp], ecx |
pop ecx |
xor ebx, ebx |
jmp .next |
.done: |
mov ebx, edx |
pop eax edx ecx edi |
sub ebx, edx |
ret |
.eof: |
mov ebx, edx |
pop eax edx ecx |
sub ebx, edx |
jmp .reteof |
;---------------------------------------------------------------- |
; |
; fs_CdReadFolder - LFN variant for reading CD disk folder |
; |
; esi points to filename /dir1/dir2/.../dirn/file,0 |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_CdReadFolder: |
push edi |
call cd_find_lfn |
jnc .found |
pop edi |
cmp [DevErrorCode], 0 |
jne .noaccess_1 |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
mov edi, [cd_current_pointer_of_input] |
test byte [edi+25], 10b ; do not allow read directories |
jnz .found_dir |
pop edi |
.noaccess_1: |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
.found_dir: |
mov eax, [edi+2] ; eax=cluster |
mov [CDSectorAddress], eax |
mov eax, [edi+10] ; ðàçìåð äèðåêòðîðèè |
.doit: |
; init header |
push eax ecx |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
pop ecx eax |
mov byte [edx], 1 ; version |
mov [cd_mem_location], edx |
add [cd_mem_location], 32 |
; íà÷èíàåì ïåðåáðîñêó ÁÄÂÊ â ÓÑÂÊ |
;.mainloop: |
mov [cd_counter_block], dword 0 |
dec dword [CDSectorAddress] |
push ecx |
.read_to_buffer: |
inc dword [CDSectorAddress] |
mov [CDDataBuf_pointer], CDDataBuf |
call ReadCDWRetr ; ÷èòàåì ñåêòîð äèðåêòîðèè |
cmp [DevErrorCode], 0 |
jne .noaccess_1 |
call .get_names_from_buffer |
sub eax,2048 |
; äèðåêòîðèÿ çàêîí÷èëàñü? |
ja .read_to_buffer |
mov edi, [cd_counter_block] |
mov [edx+8], edi |
mov edi, [ebx] |
sub [edx+4], edi |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
pop ecx edi |
mov ebx, [edx+4] |
ret |
.get_names_from_buffer: |
mov [cd_current_pointer_of_input_2],CDDataBuf |
push eax esi edi edx |
.get_names_from_buffer_1: |
call cd_get_name |
jc .end_buffer |
inc dword [cd_counter_block] |
mov eax,[cd_counter_block] |
cmp [ebx],eax |
jae .get_names_from_buffer_1 |
test ecx, ecx |
jz .get_names_from_buffer_1 |
mov edi,[cd_counter_block] |
mov [edx+4],edi |
dec ecx |
mov esi,ebp |
mov edi,[cd_mem_location] |
add edi,40 |
test dword [ebx+4], 1 ; 0=ANSI, 1=UNICODE |
jnz .unicode |
; jmp .unicode |
.ansi: |
cmp [cd_counter_block],2 |
jbe .ansi_parent_directory |
cld |
lodsw |
xchg ah,al |
call uni2ansi_char |
cld |
stosb |
; ïðîâåðêà êîíöà ôàéëà |
mov ax,[esi] |
cmp ax,word 3B00h ; ñåïàðàòîð êîíöà ôàéëà ';' |
je .cd_get_parameters_of_file_1 |
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì |
movzx eax,byte [ebp-33] |
add eax,ebp |
sub eax,34 |
cmp esi,eax |
je .cd_get_parameters_of_file_1 |
; ïðîâåðêà êîíöà ïàïêè |
movzx eax,byte [ebp-1] |
add eax,ebp |
cmp esi,eax |
jb .ansi |
.cd_get_parameters_of_file_1: |
mov [edi],byte 0 |
call cd_get_parameters_of_file |
add [cd_mem_location],304 |
jmp .get_names_from_buffer_1 |
.ansi_parent_directory: |
cmp [cd_counter_block],2 |
je @f |
mov [edi],byte '.' |
inc edi |
jmp .cd_get_parameters_of_file_1 |
@@: |
mov [edi],word '..' |
add edi,2 |
jmp .cd_get_parameters_of_file_1 |
.unicode: |
cmp [cd_counter_block],2 |
jbe .unicode_parent_directory |
cld |
movsw |
; ïðîâåðêà êîíöà ôàéëà |
mov ax,[esi] |
cmp ax,word 3B00h ; ñåïàðàòîð êîíöà ôàéëà ';' |
je .cd_get_parameters_of_file_2 |
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì |
movzx eax,byte [ebp-33] |
add eax,ebp |
sub eax,34 |
cmp esi,eax |
je .cd_get_parameters_of_file_2 |
; ïðîâåðêà êîíöà ïàïêè |
movzx eax,byte [ebp-1] |
add eax,ebp |
cmp esi,eax |
jb .unicode |
.cd_get_parameters_of_file_2: |
mov [edi],word 0 |
call cd_get_parameters_of_file |
add [cd_mem_location],560 |
jmp .get_names_from_buffer_1 |
.unicode_parent_directory: |
cmp [cd_counter_block],2 |
je @f |
mov [edi],word 2E00h ; '.' |
add edi,2 |
jmp .cd_get_parameters_of_file_2 |
@@: |
mov [edi],dword 2E002E00h ; '..' |
add edi,4 |
jmp .cd_get_parameters_of_file_2 |
.end_buffer: |
pop edx edi esi eax |
ret |
cd_get_parameters_of_file: |
mov edi,[cd_mem_location] |
cd_get_parameters_of_file_1: |
; ïîëó÷àåì àòðèáóòû ôàéëà |
xor eax,eax |
; ôàéë íå àðõèâèðîâàëñÿ |
inc eax |
shl eax,1 |
; ýòî êàòàëîã? |
test [ebp-8],byte 2 |
jz .file |
inc eax |
.file: |
; ìåòêà òîìà íå êàê â FAT, â ýòîì âèäå îòñóòñâóåò |
; ôàéë íå ÿâëÿåòñÿ ñèñòåìíûì |
shl eax,3 |
; ôàéë ÿâëÿåòñÿ ñêðûòûì? (àòðèáóò ñóùåñòâîâàíèå) |
test [ebp-8],byte 1 |
jz .hidden |
inc eax |
.hidden: |
shl eax,1 |
; ôàéë âñåãäà òîëüêî äëÿ ÷òåíèÿ, òàê êàê ýòî CD |
inc eax |
mov [edi],eax |
; ïîëó÷àåì âðåìÿ äëÿ ôàéëà |
;÷àñ |
movzx eax,byte [ebp-12] |
shl eax,8 |
;ìèíóòà |
mov al,[ebp-11] |
shl eax,8 |
;ñåêóíäà |
mov al,[ebp-10] |
;âðåìÿ ñîçäàíèÿ ôàéëà |
mov [edi+8],eax |
;âðåìÿ ïîñëåäíåãî äîñòóïà |
mov [edi+16],eax |
;âðåìÿ ïîñëåäíåé çàïèñè |
mov [edi+24],eax |
; ïîëó÷àåì äàòó äëÿ ôàéëà |
;ãîä |
movzx eax,byte [ebp-15] |
add eax,1900 |
shl eax,8 |
;ìåñÿö |
mov al,[ebp-14] |
shl eax,8 |
;äåíü |
mov al,[ebp-13] |
;äàòà ñîçäàíèÿ ôàéëà |
mov [edi+12],eax |
;âðåìÿ ïîñëåäíåãî äîñòóïà |
mov [edi+20],eax |
;âðåìÿ ïîñëåäíåé çàïèñè |
mov [edi+28],eax |
; ïîëó÷àåì òèï äàííûõ èìåíè |
xor eax,eax |
test dword [ebx+4], 1 ; 0=ANSI, 1=UNICODE |
jnz .unicode_1 |
mov [edi+4],eax |
jmp @f |
.unicode_1: |
inc eax |
mov [edi+4],eax |
@@: |
; ïîëó÷àåì ðàçìåð ôàéëà â áàéòàõ |
xor eax,eax |
mov [edi+32+4],eax |
mov eax,[ebp-23] |
mov [edi+32],eax |
ret |
;---------------------------------------------------------------- |
; |
; fs_CdGetFileInfo - LFN variant for CD |
; get file/directory attributes structure |
; |
;---------------------------------------------------------------- |
fs_CdGetFileInfo: |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 |
ret |
@@: |
push edi |
call cd_find_lfn |
pushfd |
cmp [DevErrorCode], 0 |
jz @f |
popfd |
pop edi |
mov eax, 11 |
ret |
@@: |
popfd |
jnc @f |
pop edi |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
@@: |
mov edi, edx |
push ebp |
mov ebp, [cd_current_pointer_of_input] |
add ebp, 33 |
call cd_get_parameters_of_file_1 |
pop ebp |
and dword [edi+4], 0 |
pop edi |
xor eax, eax |
ret |
;---------------------------------------------------------------- |
cd_find_lfn: |
mov [cd_appl_data],0 |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0 and [cd_current_pointer_of_input] direntry |
push eax esi |
; 16 ñåêòîð íà÷àëî íàáîðà äåñêðèïòîðîâ òîìîâ |
call WaitUnitReady |
cmp [DevErrorCode],0 |
jne .access_denied |
call prevent_medium_removal |
; òåñòîâîå ÷òåíèå |
mov [CDSectorAddress],dword 16 |
mov [CDDataBuf_pointer],CDDataBuf |
call ReadCDWRetr ;_1 |
cmp [DevErrorCode],0 |
jne .access_denied |
; âû÷èñëåíèå ïîñëåäíåé ñåññèè |
call WaitUnitReady |
cmp [DevErrorCode],0 |
jne .access_denied |
call Read_TOC |
mov ah,[CDDataBuf+4+4] |
mov al,[CDDataBuf+4+5] |
shl eax,16 |
mov ah,[CDDataBuf+4+6] |
mov al,[CDDataBuf+4+7] |
add eax,15 |
mov [CDSectorAddress],eax |
; mov [CDSectorAddress],dword 15 |
mov [CDDataBuf_pointer],CDDataBuf |
.start: |
inc dword [CDSectorAddress] |
call ReadCDWRetr ;_1 |
cmp [DevErrorCode],0 |
jne .access_denied |
.start_check: |
; ïðîâåðêà íà âøèâîñòü |
cmp [CDDataBuf+1],dword 'CD00' |
jne .access_denied |
cmp [CDDataBuf+5],byte '1' |
jne .access_denied |
; ñåêòîð ÿâëÿåòñÿ òåðìèíàòîðîì íàáîð äåñêðèïòîðîâ òîìîâ? |
cmp [CDDataBuf],byte 0xff |
je .access_denied |
; ñåêòîð ÿâëÿåòñÿ äîïîëíèòåëüíûì è óëó÷øåííûì äåñêðèïòîðîì òîìà? |
cmp [CDDataBuf],byte 0x2 |
jne .start |
; ñåêòîð ÿâëÿåòñÿ äîïîëíèòåëüíûì äåñêðèïòîðîì òîìà? |
cmp [CDDataBuf+6],byte 0x1 |
jne .start |
; ïàðàìåòðû root äèðåêòðîðèè |
mov eax,[CDDataBuf+0x9c+2] ; íà÷àëî root äèðåêòðîðèè |
mov [CDSectorAddress],eax |
mov eax,[CDDataBuf+0x9c+10] ; ðàçìåð root äèðåêòðîðèè |
cmp byte [esi], 0 |
jnz @f |
mov [cd_current_pointer_of_input],CDDataBuf+0x9c |
jmp .done |
@@: |
; íà÷èíàåì ïîèñê |
.mainloop: |
dec dword [CDSectorAddress] |
.read_to_buffer: |
inc dword [CDSectorAddress] |
mov [CDDataBuf_pointer],CDDataBuf |
call ReadCDWRetr ; ÷èòàåì ñåêòîð äèðåêòîðèè |
cmp [DevErrorCode],0 |
jne .access_denied |
push ebp |
call cd_find_name_in_buffer |
pop ebp |
jnc .found |
sub eax,2048 |
; äèðåêòîðèÿ çàêîí÷èëàñü? |
cmp eax,0 |
ja .read_to_buffer |
; íåò èñêîìîãî ýëåìåíòà öåïî÷êè |
.access_denied: |
pop esi eax |
mov [cd_appl_data],1 |
stc |
ret |
; èñêîìûé ýëåìåíò öåïî÷êè íàéäåí |
.found: |
; êîíåö ïóòè ôàéëà |
cmp byte [esi-1], 0 |
jz .done |
.nested: |
mov eax,[cd_current_pointer_of_input] |
push dword [eax+2] |
pop dword [CDSectorAddress] ; íà÷àëî äèðåêòîðèè |
mov eax,[eax+2+8] ; ðàçìåð äèðåêòîðèè |
jmp .mainloop |
; óêàçàòåëü ôàéëà íàéäåí |
.done: |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .nested |
@@: |
pop esi eax |
mov [cd_appl_data],1 |
clc |
ret |
cd_find_name_in_buffer: |
mov [cd_current_pointer_of_input_2],CDDataBuf |
.start: |
call cd_get_name |
jc .not_found |
call cd_compare_name |
jc .start |
.found: |
clc |
ret |
.not_found: |
stc |
ret |
cd_get_name: |
push eax |
mov ebp,[cd_current_pointer_of_input_2] |
mov [cd_current_pointer_of_input],ebp |
mov eax,[ebp] |
test eax,eax ; âõîäû çàêîí÷èëèñü? |
jz .next_sector |
cmp ebp,CDDataBuf+2048 ; áóôåð çàêîí÷èëñÿ? |
jae .next_sector |
movzx eax, byte [ebp] |
add [cd_current_pointer_of_input_2],eax ; ñëåäóþùèé âõîä êàòàëîãà |
add ebp,33 ; óêàçàòåëü óñòàíîâëåí íà íà÷àëî èìåíè |
pop eax |
clc |
ret |
.next_sector: |
pop eax |
stc |
ret |
cd_compare_name: |
; compares ASCIIZ-names, case-insensitive (cp866 encoding) |
; in: esi->name, ebp->name |
; out: if names match: ZF=1 and esi->next component of name |
; else: ZF=0, esi is not changed |
; destroys eax |
push esi eax edi |
mov edi,ebp |
.loop: |
cld |
lodsb |
push eax |
call char_todown |
call ansi2uni_char |
xchg ah,al |
scasw |
pop eax |
je .coincides |
call char_toupper |
call ansi2uni_char |
xchg ah,al |
sub edi,2 |
scasw |
jne .name_not_coincide |
.coincides: |
cmp [esi],byte '/' ; ðàçäåëèòåëü ïóòè, êîíåö èìåíè òåêóùåãî ýëåìåíòà |
je .done |
cmp [esi],byte 0 ; ðàçäåëèòåëü ïóòè, êîíåö èìåíè òåêóùåãî ýëåìåíòà |
je .done |
jmp .loop |
.name_not_coincide: |
pop edi eax esi |
stc |
ret |
.done: |
; ïðîâåðêà êîíöà ôàéëà |
cmp [edi],word 3B00h ; ñåïàðàòîð êîíöà ôàéëà ';' |
je .done_1 |
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì |
movzx eax,byte [ebp-33] |
add eax,ebp |
sub eax,34 |
cmp edi,eax |
je .done_1 |
; ïðîâåðêà êîíöà ïàïêè |
movzx eax,byte [ebp-1] |
add eax,ebp |
cmp edi,eax |
jne .name_not_coincide |
.done_1: |
pop edi eax |
add esp,4 |
inc esi |
clc |
ret |
char_todown: |
; convert character to uppercase, using cp866 encoding |
; in: al=symbol |
; out: al=converted symbol |
cmp al, 'A' |
jb .ret |
cmp al, 'Z' |
jbe .az |
cmp al, '' |
jb .ret |
cmp al, '' |
jb .rus1 |
cmp al, '' |
ja .ret |
; 0x90-0x9F -> 0xE0-0xEF |
add al, 'à'-'' |
.ret: |
ret |
.rus1: |
; 0x80-0x8F -> 0xA0-0xAF |
.az: |
add al, 0x20 |
ret |
uni2ansi_char: |
; convert UNICODE character in al to ANSI character in ax, using cp866 encoding |
; in: ax=UNICODE character |
; out: al=converted ANSI character |
cmp ax, 0x80 |
jb .ascii |
cmp ax, 0x401 |
jz .yo1 |
cmp ax, 0x451 |
jz .yo2 |
cmp ax, 0x410 |
jb .unk |
cmp ax, 0x440 |
jb .rus1 |
cmp ax, 0x450 |
jb .rus2 |
.unk: |
mov al, '_' |
jmp .doit |
.yo1: |
mov al, 'ð' |
jmp .doit |
.yo2: |
mov al, 'ñ' |
jmp .doit |
.rus1: |
; 0x410-0x43F -> 0x80-0xAF |
add al, 0x70 |
jmp .doit |
.rus2: |
; 0x440-0x44F -> 0xE0-0xEF |
add al, 0xA0 |
.ascii: |
.doit: |
ret |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/fs/ntfs.inc |
---|
0,0 → 1,1829 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
ntfs_test_bootsec: |
; in: ebx->buffer, edx=size of partition |
; out: CF set <=> invalid |
; 1. Name=='NTFS ' |
cmp dword [ebx+3], 'NTFS' |
jnz .no |
cmp dword [ebx+7], ' ' |
jnz .no |
; 2. Number of bytes per sector is the same as for physical device |
; (that is, 0x200 for hard disk) |
cmp word [ebx+11], 0x200 |
jnz .no |
; 3. Number of sectors per cluster must be power of 2 |
movzx eax, byte [ebx+13] |
dec eax |
js .no |
test al, [ebx+13] |
jnz .no |
; 4. FAT parameters must be zero |
cmp word [ebx+14], 0 |
jnz .no |
cmp dword [ebx+16], 0 |
jnz .no |
cmp byte [ebx+20], 0 |
jnz .no |
cmp word [ebx+22], 0 |
jnz .no |
cmp dword [ebx+32], 0 |
jnz .no |
; 5. Number of sectors <= partition size |
cmp dword [ebx+0x2C], 0 |
ja .no |
cmp [ebx+0x28], edx |
ja .no |
; 6. $MFT and $MFTMirr clusters must be within partition |
cmp dword [ebx+0x34], 0 |
ja .no |
push edx |
movzx eax, byte [ebx+13] |
mul dword [ebx+0x30] |
test edx, edx |
pop edx |
jnz .no |
cmp eax, edx |
ja .no |
cmp dword [ebx+0x3C], 0 |
ja .no |
push edx |
movzx eax, byte [ebx+13] |
mul dword [ebx+0x38] |
test edx, edx |
pop edx |
jnz .no |
cmp eax, edx |
ja .no |
; 7. Clusters per FRS must be either negative and in [-31,-9] or positive and power of 2 |
movsx eax, byte [ebx+0x40] |
cmp al, -31 |
jl .no |
cmp al, -9 |
jle @f |
dec eax |
js .no |
test [ebx+0x40], al |
jnz .no |
@@: |
; 8. Same for clusters per IndexAllocationBuffer |
movsx eax, byte [ebx+0x44] |
cmp al, -31 |
jl .no |
cmp al, -9 |
jle @f |
dec eax |
js .no |
test [ebx+0x44], al |
jnz .no |
@@: |
; OK, this is correct NTFS bootsector |
clc |
ret |
.no: |
; No, this bootsector isn't NTFS |
stc |
ret |
ntfs_setup: ; CODE XREF: part_set.inc |
; By given bootsector, initialize some NTFS variables |
; call ntfs_test_bootsec ; checking boot sector was already |
; jc problem_fat_dec_count |
movzx eax, byte [ebx+13] |
mov [ntfs_data.sectors_per_cluster], eax |
mov eax, [ebx+0x28] |
add eax, [PARTITION_START] |
dec eax |
mov [PARTITION_END], eax |
mov [fs_type], 1 |
mov eax, [ebx+0x30] |
mov [ntfs_data.mft_cluster], eax |
mov eax, [ebx+0x38] |
mov [ntfs_data.mftmirr_cluster], eax |
movsx eax, byte [ebx+0x40] |
test eax, eax |
js .1 |
mul [ntfs_data.sectors_per_cluster] |
shl eax, 9 |
jmp .2 |
.1: |
neg eax |
mov ecx, eax |
mov eax, 1 |
shl eax, cl |
.2: |
mov [ntfs_data.frs_size], eax |
movsx eax, byte [ebx+0x44] |
test eax, eax |
js .3 |
mul [ntfs_data.sectors_per_cluster] |
shl eax, 9 |
jmp .4 |
.3: |
neg eax |
mov ecx, eax |
mov eax, 1 |
shl eax, cl |
.4: |
mov [ntfs_data.iab_size], eax |
; allocate space for buffers |
add eax, [ntfs_data.frs_size] |
push eax |
call kernel_alloc |
test eax, eax |
jz problem_fat_dec_count |
mov [ntfs_data.frs_buffer], eax |
add eax, [ntfs_data.frs_size] |
mov [ntfs_data.iab_buffer], eax |
; read $MFT disposition |
mov eax, [ntfs_data.mft_cluster] |
mul [ntfs_data.sectors_per_cluster] |
call ntfs_read_frs_sector |
cmp [hd_error], 0 |
jnz .usemirr |
cmp dword [ebx], 'FILE' |
jnz .usemirr |
call ntfs_restore_usa_frs |
jnc .mftok |
.usemirr: |
and [hd_error], 0 |
mov eax, [ntfs_data.mftmirr_cluster] |
mul [ntfs_data.sectors_per_cluster] |
call ntfs_read_frs_sector |
cmp [hd_error], 0 |
jnz @f |
cmp dword [ebx], 'FILE' |
jnz @f |
call ntfs_restore_usa_frs |
jnc .mftok |
@@: |
; $MFT and $MFTMirr invalid! |
.fail_free_frs: |
push [ntfs_data.frs_buffer] |
call kernel_free |
jmp problem_fat_dec_count |
.fail_free_mft: |
push [ntfs_data.mft_retrieval] |
call kernel_free |
jmp .fail_free_frs |
.mftok: |
; read $MFT table retrieval information |
; start with one page, increase if not enough (when MFT too fragmented) |
push ebx |
push 0x1000 |
call kernel_alloc |
pop ebx |
test eax, eax |
jz .fail_free_frs |
mov [ntfs_data.mft_retrieval], eax |
and [ntfs_data.mft_retrieval_size], 0 |
mov [ntfs_data.mft_retrieval_alloc], 0x1000/8 |
; $MFT base record must contain unnamed non-resident $DATA attribute |
movzx eax, word [ebx+14h] |
add eax, ebx |
.scandata: |
cmp dword [eax], -1 |
jz .fail_free_mft |
cmp dword [eax], 0x80 |
jnz @f |
cmp byte [eax+9], 0 |
jz .founddata |
@@: |
add eax, [eax+4] |
jmp .scandata |
.founddata: |
cmp byte [eax+8], 0 |
jz .fail_free_mft |
; load first portion of $DATA attribute retrieval information |
mov edx, [eax+0x18] |
mov [ntfs_data.mft_retrieval_end], edx |
mov esi, eax |
movzx eax, word [eax+0x20] |
add esi, eax |
sub esp, 10h |
.scanmcb: |
call ntfs_decode_mcb_entry |
jnc .scanmcbend |
call .get_mft_retrieval_ptr |
mov edx, [esp] ; block length |
mov [eax], edx |
mov edx, [esp+8] ; block addr (relative) |
mov [eax+4], edx |
inc [ntfs_data.mft_retrieval_size] |
jmp .scanmcb |
.scanmcbend: |
add esp, 10h |
; there may be other portions of $DATA attribute in auxiliary records; |
; if they will be needed, they will be loaded later |
mov [ntfs_data.cur_index_size], 0x1000/0x200 |
push 0x1000 |
call kernel_alloc |
test eax, eax |
jz .fail_free_mft |
mov [ntfs_data.cur_index_buf], eax |
popad |
call free_hd_channel |
and [hd1_status], 0 |
ret |
.get_mft_retrieval_ptr: |
pushad |
mov eax, [ntfs_data.mft_retrieval_size] |
cmp eax, [ntfs_data.mft_retrieval_alloc] |
jnz .ok |
add eax, 0x1000/8 |
mov [ntfs_data.mft_retrieval_alloc], eax |
shl eax, 3 |
push eax |
call kernel_alloc |
test eax, eax |
jnz @f |
popad |
add esp, 14h |
jmp .fail_free_mft |
@@: |
mov esi, [ntfs_data.mft_retrieval] |
mov edi, eax |
mov ecx, [ntfs_data.mft_retrieval_size] |
add ecx, ecx |
rep movsd |
push [ntfs_data.mft_retrieval] |
mov [ntfs_data.mft_retrieval], eax |
call kernel_free |
mov eax, [ntfs_data.mft_retrieval_size] |
.ok: |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
mov [esp+28], eax |
popad |
ret |
ntfs_read_frs_sector: |
push eax ecx |
add eax, [PARTITION_START] |
mov ecx, [ntfs_data.frs_size] |
shr ecx, 9 |
mov ebx, [ntfs_data.frs_buffer] |
push ebx |
@@: |
call hd_read |
cmp [hd_error], 0 |
jnz .fail |
add ebx, 0x200 |
inc eax |
loop @b |
.fail: |
pop ebx |
pop ecx eax |
ret |
uglobal |
align 4 |
ntfs_cur_attr dd ? |
ntfs_cur_iRecord dd ? |
ntfs_cur_offs dd ? ; in sectors |
ntfs_cur_size dd ? ; in sectors |
ntfs_cur_buf dd ? |
ntfs_cur_read dd ? ; [output] |
ntfs_bCanContinue db ? |
rb 3 |
ntfs_attrlist_buf rb 0x400 |
ntfs_attrlist_mft_buf rb 0x400 |
ntfs_bitmap_buf rb 0x400 |
ntfs_attr_iRecord dd ? |
ntfs_attr_iBaseRecord dd ? |
ntfs_attr_offs dd ? |
ntfs_attr_list dd ? |
ntfs_attr_size dq ? |
ntfs_cur_tail dd ? |
endg |
ntfs_read_attr: |
; in: global variables |
; out: [ntfs_cur_read] |
pushad |
and [ntfs_cur_read], 0 |
cmp [ntfs_cur_iRecord], 0 |
jnz .nomft |
cmp [ntfs_cur_attr], 0x80 |
jnz .nomft |
mov eax, [ntfs_data.mft_retrieval_end] |
inc eax |
mul [ntfs_data.sectors_per_cluster] |
cmp eax, [ntfs_cur_offs] |
jbe .nomft |
; precalculated part of $Mft $DATA |
mov esi, [ntfs_data.mft_retrieval] |
mov eax, [ntfs_cur_offs] |
xor edx, edx |
div [ntfs_data.sectors_per_cluster] |
; eax = VCN, edx = offset in sectors from beginning of cluster |
xor ecx, ecx ; ecx will contain LCN |
.mftscan: |
add ecx, [esi+4] |
sub eax, [esi] |
jb @f |
add esi, 8 |
push eax |
mov eax, [ntfs_data.mft_retrieval_end] |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
cmp eax, esi |
pop eax |
jnz .mftscan |
jmp .nomft |
@@: |
push ecx |
add ecx, eax |
add ecx, [esi] |
push eax |
push edx |
mov eax, [ntfs_data.sectors_per_cluster] |
mul ecx |
; eax = sector on partition |
add eax, [PARTITION_START] |
pop edx |
add eax, edx |
mov ebx, [ntfs_cur_buf] |
pop ecx |
neg ecx |
imul ecx, [ntfs_data.sectors_per_cluster] |
sub ecx, edx |
cmp ecx, [ntfs_cur_size] |
jb @f |
mov ecx, [ntfs_cur_size] |
@@: |
; ecx = number of sequential sectors to read |
call hd_read |
cmp [hd_error], 0 |
jnz .errread |
add [ntfs_cur_read], 0x200 |
dec [ntfs_cur_size] |
inc [ntfs_cur_offs] |
add ebx, 0x200 |
mov [ntfs_cur_buf], ebx |
inc eax |
loop @b |
pop ecx |
xor eax, eax |
xor edx, edx |
cmp [ntfs_cur_size], eax |
jz @f |
add esi, 8 |
push eax |
mov eax, [ntfs_data.mft_retrieval_end] |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
cmp eax, esi |
pop eax |
jz .nomft |
jmp .mftscan |
@@: |
popad |
ret |
.errread: |
pop ecx |
.errret: |
stc |
popad |
ret |
.nomft: |
; 1. Read file record. |
; N.B. This will do recursive call of read_attr for $MFT::$Data. |
mov eax, [ntfs_cur_iRecord] |
mov [ntfs_attr_iRecord], eax |
and [ntfs_attr_list], 0 |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
or [ntfs_attr_iBaseRecord], -1 |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
; 2. Find required attribute. |
mov eax, [ntfs_data.frs_buffer] |
; a) For auxiliary records, read base record |
; N.B. If base record is present, |
; base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero |
cmp dword [eax+24h], 0 |
jz @f |
mov eax, [eax+20h] |
; test eax, eax |
; jz @f |
.beginfindattr: |
mov [ntfs_attr_iRecord], eax |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
@@: |
; b) Scan for required attribute and for $ATTR_LIST |
mov eax, [ntfs_data.frs_buffer] |
movzx ecx, word [eax+14h] |
add eax, ecx |
mov ecx, [ntfs_cur_attr] |
and [ntfs_attr_offs], 0 |
.scanattr: |
cmp dword [eax], -1 |
jz .scandone |
cmp dword [eax], ecx |
jz .okattr |
cmp [ntfs_attr_iBaseRecord], -1 |
jnz .scancont |
cmp dword [eax], 0x20 ; $ATTR_LIST |
jnz .scancont |
mov [ntfs_attr_list], eax |
jmp .scancont |
.okattr: |
; ignore named $DATA attributes (aka NTFS streams) |
cmp ecx, 0x80 |
jnz @f |
cmp byte [eax+9], 0 |
jnz .scancont |
@@: |
mov [ntfs_attr_offs], eax |
.scancont: |
add eax, [eax+4] |
jmp .scanattr |
.continue: |
pushad |
and [ntfs_cur_read], 0 |
.scandone: |
; c) Check for required offset and length |
mov ecx, [ntfs_attr_offs] |
jecxz .noattr |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
call .doreadattr |
pop edx |
pop eax |
jc @f |
cmp [ntfs_bCanContinue], 0 |
jz @f |
sub edx, [ntfs_cur_read] |
neg edx |
shr edx, 9 |
sub eax, edx |
mov [ntfs_cur_size], eax |
jnz .not_in_cur |
@@: |
popad |
ret |
.noattr: |
.not_in_cur: |
cmp [ntfs_cur_attr], 0x20 |
jz @f |
mov ecx, [ntfs_attr_list] |
test ecx, ecx |
jnz .lookattr |
.ret_is_attr: |
cmp [ntfs_attr_offs], 1 ; CF set <=> ntfs_attr_offs == 0 |
popad |
ret |
.lookattr: |
; required attribute or required offset was not found in base record; |
; it may be present in auxiliary records; |
; scan $ATTR_LIST |
mov eax, [ntfs_attr_iBaseRecord] |
cmp eax, -1 |
jz @f |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
or [ntfs_attr_iBaseRecord], -1 |
@@: |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
push [ntfs_cur_buf] |
push dword [ntfs_attr_size] |
push dword [ntfs_attr_size+4] |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 2 |
and [ntfs_cur_read], 0 |
mov eax, ntfs_attrlist_buf |
cmp [ntfs_cur_iRecord], 0 |
jnz @f |
mov eax, ntfs_attrlist_mft_buf |
@@: |
mov [ntfs_cur_buf], eax |
push eax |
call .doreadattr |
pop esi |
mov edx, 1 |
pop dword [ntfs_attr_size+4] |
pop dword [ntfs_attr_size] |
mov ebp, [ntfs_cur_read] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_read] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
jc .errret |
or edi, -1 |
lea ebp, [ebp+esi-1Ah] |
.scanliststart: |
mov eax, [ntfs_cur_attr] |
.scanlist: |
cmp esi, ebp |
jae .scanlistdone |
cmp eax, [esi] |
jz @f |
.scanlistcont: |
movzx ecx, word [esi+4] |
add esi, ecx |
jmp .scanlist |
@@: |
; ignore named $DATA attributes (aka NTFS streams) |
cmp eax, 0x80 |
jnz @f |
cmp byte [esi+6], 0 |
jnz .scanlistcont |
@@: |
push eax |
mov eax, [esi+8] |
test eax, eax |
jnz .testf |
mov eax, dword [ntfs_attr_size] |
and eax, dword [ntfs_attr_size+4] |
cmp eax, -1 |
jnz .testfz |
; if attribute is in auxiliary records, its size is defined only in first |
mov eax, [esi+10h] |
call ntfs_read_file_record |
test eax, eax |
jnz @f |
.errret_pop: |
pop eax |
jmp .errret |
@@: |
mov eax, [ntfs_data.frs_buffer] |
movzx ecx, word [eax+14h] |
add eax, ecx |
mov ecx, [ntfs_cur_attr] |
@@: |
cmp dword [eax], -1 |
jz .errret_pop |
cmp dword [eax], ecx |
jz @f |
.l1: |
add eax, [eax+4] |
jmp @b |
@@: |
cmp eax, 0x80 |
jnz @f |
cmp byte [eax+9], 0 |
jnz .l1 |
@@: |
cmp byte [eax+8], 0 |
jnz .sdnores |
mov eax, [eax+10h] |
mov dword [ntfs_attr_size], eax |
and dword [ntfs_attr_size+4], 0 |
jmp .testfz |
.sdnores: |
mov ecx, [eax+30h] |
mov dword [ntfs_attr_size], ecx |
mov ecx, [eax+34h] |
mov dword [ntfs_attr_size+4], ecx |
.testfz: |
xor eax, eax |
.testf: |
imul eax, [ntfs_data.sectors_per_cluster] |
cmp eax, [ntfs_cur_offs] |
pop eax |
ja @f |
mov edi, [esi+10h] ; keep previous iRecord |
jmp .scanlistcont |
@@: |
.scanlistfound: |
cmp edi, -1 |
jnz @f |
popad |
ret |
@@: |
mov eax, [ntfs_cur_iRecord] |
mov [ntfs_attr_iBaseRecord], eax |
mov eax, edi |
jmp .beginfindattr |
.sde: |
popad |
stc |
ret |
.scanlistdone: |
sub ebp, ntfs_attrlist_buf-1Ah |
cmp [ntfs_cur_iRecord], 0 |
jnz @f |
sub ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf |
@@: |
cmp ebp, 0x400 |
jnz .scanlistfound |
inc edx |
push esi edi |
mov esi, ntfs_attrlist_buf+0x200 |
mov edi, ntfs_attrlist_buf |
cmp [ntfs_cur_iRecord], 0 |
jnz @f |
mov esi, ntfs_attrlist_mft_buf+0x200 |
mov edi, ntfs_attrlist_mft_buf |
@@: |
mov ecx, 0x200/4 |
rep movsd |
mov eax, edi |
pop edi esi |
sub esi, 0x200 |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
push [ntfs_cur_buf] |
push dword [ntfs_attr_size] |
push dword [ntfs_attr_size+4] |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
mov [ntfs_cur_offs], edx |
mov [ntfs_cur_size], 1 |
and [ntfs_cur_read], 0 |
mov [ntfs_cur_buf], eax |
mov ecx, [ntfs_attr_list] |
push esi edx |
call .doreadattr |
pop edx esi |
mov ebp, [ntfs_cur_read] |
pop dword [ntfs_attr_size+4] |
pop dword [ntfs_attr_size] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_read] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
jc .errret |
add ebp, ntfs_attrlist_buf+0x200-0x1A |
cmp [ntfs_cur_iRecord], 0 |
jnz .scanliststart |
add ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf |
jmp .scanliststart |
.doreadattr: |
mov [ntfs_bCanContinue], 0 |
cmp byte [ecx+8], 0 |
jnz .nonresident |
mov eax, [ecx+10h] ; length |
mov esi, eax |
mov edx, [ntfs_cur_offs] |
shr eax, 9 |
cmp eax, edx |
jb .okret |
shl edx, 9 |
sub esi, edx |
movzx eax, word [ecx+14h] |
add edx, eax |
add edx, ecx ; edx -> data |
mov eax, [ntfs_cur_size] |
cmp eax, (0xFFFFFFFF shr 9)+1 |
jbe @f |
mov eax, (0xFFFFFFFF shr 9)+1 |
@@: |
shl eax, 9 |
cmp eax, esi |
jbe @f |
mov eax, esi |
@@: |
; eax = length, edx -> data |
mov [ntfs_cur_read], eax |
mov ecx, eax |
mov eax, edx |
mov ebx, [ntfs_cur_buf] |
call memmove |
and [ntfs_cur_size], 0 ; CF=0 |
ret |
.nonresident: |
; Not all auxiliary records contain correct FileSize info |
mov eax, dword [ntfs_attr_size] |
mov edx, dword [ntfs_attr_size+4] |
push eax |
and eax, edx |
cmp eax, -1 |
pop eax |
jnz @f |
mov eax, [ecx+30h] ; FileSize |
mov edx, [ecx+34h] |
mov dword [ntfs_attr_size], eax |
mov dword [ntfs_attr_size+4], edx |
@@: |
add eax, 0x1FF |
adc edx, 0 |
shrd eax, edx, 9 |
sub eax, [ntfs_cur_offs] |
ja @f |
; return with nothing read |
and [ntfs_cur_size], 0 |
.okret: |
clc |
ret |
@@: |
; reduce read length |
and [ntfs_cur_tail], 0 |
cmp [ntfs_cur_size], eax |
jb @f |
mov [ntfs_cur_size], eax |
mov eax, dword [ntfs_attr_size] |
and eax, 0x1FF |
mov [ntfs_cur_tail], eax |
@@: |
cmp [ntfs_cur_size], 0 |
jz .okret |
mov eax, [ntfs_cur_offs] |
xor edx, edx |
div [ntfs_data.sectors_per_cluster] |
sub eax, [ecx+10h] ; first_vbo |
jb .okret |
; eax = cluster, edx = starting sector |
sub esp, 10h |
movzx esi, word [ecx+20h] ; mcb_info_ofs |
add esi, ecx |
xor ebp, ebp |
.readloop: |
call ntfs_decode_mcb_entry |
jnc .break |
add ebp, [esp+8] |
sub eax, [esp] |
jae .readloop |
push ecx |
push eax |
add eax, [esp+8] |
add eax, ebp |
imul eax, [ntfs_data.sectors_per_cluster] |
add eax, edx |
add eax, [PARTITION_START] |
pop ecx |
neg ecx |
imul ecx, [ntfs_data.sectors_per_cluster] |
sub ecx, edx |
cmp ecx, [ntfs_cur_size] |
jb @f |
mov ecx, [ntfs_cur_size] |
@@: |
mov ebx, [ntfs_cur_buf] |
@@: |
call hd_read |
cmp [hd_error], 0 |
jnz .errread2 |
add ebx, 0x200 |
mov [ntfs_cur_buf], ebx |
inc eax |
add [ntfs_cur_read], 0x200 |
dec [ntfs_cur_size] |
inc [ntfs_cur_offs] |
loop @b |
pop ecx |
xor eax, eax |
xor edx, edx |
cmp [ntfs_cur_size], 0 |
jnz .readloop |
add esp, 10h |
mov eax, [ntfs_cur_tail] |
test eax, eax |
jz @f |
sub eax, 0x200 |
add [ntfs_cur_read], eax |
@@: |
clc |
ret |
.errread2: |
pop ecx |
add esp, 10h |
stc |
ret |
.break: |
add esp, 10h ; CF=0 |
mov [ntfs_bCanContinue], 1 |
ret |
ntfs_read_file_record: |
; in: eax=iRecord |
; out: [ntfs_data.frs_buffer] contains information |
; eax=0 - failed, eax=1 - success |
; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size] |
push ecx edx |
mov ecx, [ntfs_data.frs_size] |
mul ecx |
shrd eax, edx, 9 |
shr edx, 9 |
jnz .err |
push [ntfs_attr_iRecord] |
push [ntfs_attr_iBaseRecord] |
push [ntfs_attr_offs] |
push [ntfs_attr_list] |
push dword [ntfs_attr_size+4] |
push dword [ntfs_attr_size] |
push [ntfs_cur_iRecord] |
push [ntfs_cur_attr] |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_buf] |
push [ntfs_cur_read] |
mov [ntfs_cur_attr], 0x80 ; $DATA |
and [ntfs_cur_iRecord], 0 ; $Mft |
mov [ntfs_cur_offs], eax |
shr ecx, 9 |
mov [ntfs_cur_size], ecx |
mov eax, [ntfs_data.frs_buffer] |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
mov eax, [ntfs_cur_read] |
pop [ntfs_cur_read] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
pop [ntfs_cur_attr] |
pop [ntfs_cur_iRecord] |
pop dword [ntfs_attr_size] |
pop dword [ntfs_attr_size+4] |
pop [ntfs_attr_list] |
pop [ntfs_attr_offs] |
pop [ntfs_attr_iBaseRecord] |
pop [ntfs_attr_iRecord] |
pop edx ecx |
jc .errret |
cmp eax, [ntfs_data.frs_size] |
jnz .errret |
mov eax, [ntfs_data.frs_buffer] |
cmp dword [eax], 'FILE' |
jnz .errret |
push ebx |
mov ebx, eax |
call ntfs_restore_usa_frs |
pop ebx |
setnc al |
movzx eax, al |
.ret: |
ret |
.err: |
pop edx ecx |
.errret: |
xor eax, eax |
ret |
ntfs_restore_usa_frs: |
mov eax, [ntfs_data.frs_size] |
ntfs_restore_usa: |
pushad |
shr eax, 9 |
mov ecx, eax |
inc eax |
cmp [ebx+6], ax |
jnz .err |
movzx eax, word [ebx+4] |
lea esi, [eax+ebx] |
lodsw |
mov edx, eax |
lea edi, [ebx+0x1FE] |
@@: |
cmp [edi], dx |
jnz .err |
lodsw |
stosw |
add edi, 0x1FE |
loop @b |
popad |
clc |
ret |
.err: |
popad |
stc |
ret |
ntfs_decode_mcb_entry: |
push eax ecx edi |
lea edi, [esp+16] |
xor eax, eax |
lodsb |
test al, al |
jz .end |
mov ecx, eax |
and ecx, 0xF |
cmp ecx, 8 |
ja .end |
push ecx |
rep movsb |
pop ecx |
sub ecx, 8 |
neg ecx |
cmp byte [esi-1], 80h |
jae .end |
push eax |
xor eax, eax |
rep stosb |
pop ecx |
shr ecx, 4 |
cmp ecx, 8 |
ja .end |
push ecx |
rep movsb |
pop ecx |
sub ecx, 8 |
neg ecx |
cmp byte [esi-1], 80h |
cmc |
sbb eax, eax |
rep stosb |
stc |
.end: |
pop edi ecx eax |
ret |
unichar_toupper: |
push eax |
call uni2ansi_char |
cmp al, '_' |
jz .unk |
add esp, 4 |
call char_toupper |
jmp ansi2uni_char |
.unk: |
pop eax |
ret |
ntfs_find_lfn: |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0, [ntfs_cur_iRecord] valid, eax->record in parent directory |
mov [ntfs_cur_iRecord], 5 ; start parse from root cluster |
.doit2: |
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT |
and [ntfs_cur_offs], 0 |
mov eax, [ntfs_data.cur_index_size] |
mov [ntfs_cur_size], eax |
mov eax, [ntfs_data.cur_index_buf] |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
jnc @f |
.ret: |
ret |
@@: |
cmp [ntfs_cur_read], 0x20 |
jc .ret |
pushad |
mov esi, [ntfs_data.cur_index_buf] |
mov eax, [esi+14h] |
add eax, 10h |
cmp [ntfs_cur_read], eax |
jae .readok1 |
add eax, 1FFh |
shr eax, 9 |
cmp eax, [ntfs_data.cur_index_size] |
ja @f |
.stc_ret: |
popad |
stc |
ret |
@@: |
; reallocate |
push eax |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop eax |
mov [ntfs_data.cur_index_size], eax |
push eax |
call kernel_alloc |
test eax, eax |
jnz @f |
and [ntfs_data.cur_index_size], 0 |
and [ntfs_data.cur_index_buf], 0 |
jmp .stc_ret |
@@: |
mov [ntfs_data.cur_index_buf], eax |
popad |
jmp .doit2 |
.readok1: |
mov ebp, [esi+8] ; subnode_size |
shr ebp, 9 |
cmp ebp, [ntfs_data.cur_index_size] |
jbe .ok2 |
push esi ebp |
push ebp |
call kernel_alloc |
pop ebp esi |
test eax, eax |
jz .stc_ret |
mov edi, eax |
mov ecx, [ntfs_data.cur_index_size] |
shl ecx, 9-2 |
rep movsd |
mov esi, eax |
mov [ntfs_data.cur_index_size], ebp |
push esi ebp |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop ebp esi |
mov [ntfs_data.cur_index_buf], esi |
.ok2: |
add esi, 10h |
mov edi, [esp+4] |
; edi -> name, esi -> current index data, ebp = subnode size |
.scanloop: |
add esi, [esi] |
.scanloopint: |
test byte [esi+0Ch], 2 |
jnz .subnode |
push esi |
add esi, 0x52 |
movzx ecx, byte [esi-2] |
push edi |
@@: |
lodsw |
call unichar_toupper |
push eax |
mov al, [edi] |
inc edi |
cmp al, '/' |
jz .slash |
call char_toupper |
call ansi2uni_char |
cmp ax, [esp] |
pop eax |
loopz @b |
jz .found |
pop edi |
pop esi |
jb .subnode |
.scanloopcont: |
movzx eax, word [esi+8] |
add esi, eax |
jmp .scanloopint |
.slash: |
pop eax |
pop edi |
pop esi |
.subnode: |
test byte [esi+0Ch], 1 |
jz .notfound |
movzx eax, word [esi+8] |
mov eax, [esi+eax-8] |
mul [ntfs_data.sectors_per_cluster] |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_attr], 0xA0 ; $INDEX_ALLOCATION |
mov [ntfs_cur_size], ebp |
mov eax, [ntfs_data.cur_index_buf] |
mov esi, eax |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
mov eax, ebp |
shl eax, 9 |
cmp [ntfs_cur_read], eax |
jnz .notfound |
cmp dword [esi], 'INDX' |
jnz .notfound |
mov ebx, esi |
call ntfs_restore_usa |
jc .notfound |
add esi, 0x18 |
jmp .scanloop |
.notfound: |
popad |
stc |
ret |
.found: |
cmp byte [edi], 0 |
jz .done |
cmp byte [edi], '/' |
jz .next |
pop edi |
pop esi |
jmp .scanloopcont |
.done: |
.next: |
pop esi |
pop esi |
mov eax, [esi] |
mov [ntfs_cur_iRecord], eax |
mov [esp+1Ch], esi |
mov [esp+4], edi |
popad |
inc esi |
cmp byte [esi-1], 0 |
jnz .doit2 |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .doit2 |
@@: |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdRead - read NTFS hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdRead: |
cmp byte [esi], 0 |
jnz @f |
or ebx, -1 |
push ERROR_ACCESS_DENIED |
pop eax |
ret |
@@: |
call ntfs_find_lfn |
jnc .found |
or ebx, -1 |
push ERROR_FILE_NOT_FOUND |
pop eax |
ret |
.found: |
mov [ntfs_cur_attr], 0x80 ; $DATA |
and [ntfs_cur_offs], 0 |
and [ntfs_cur_size], 0 |
call ntfs_read_attr |
jnc @f |
or ebx, -1 |
push ERROR_ACCESS_DENIED |
pop eax |
ret |
@@: |
pushad |
and dword [esp+10h], 0 |
xor eax, eax |
test ebx, ebx |
jz .zero1 |
cmp dword [ebx+4], 0x200 |
jb @f |
.eof0: |
popad |
xor ebx, ebx |
.eof: |
push ERROR_END_OF_FILE |
pop eax |
ret |
@@: |
mov eax, [ebx] |
test eax, 0x1FF |
jz .alignedstart |
push edx |
mov edx, [ebx+4] |
shrd eax, edx, 9 |
pop edx |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
call ntfs_read_attr.continue |
mov eax, [ebx] |
and eax, 0x1FF |
lea esi, [ntfs_bitmap_buf+eax] |
sub eax, [ntfs_cur_read] |
jae .eof0 |
neg eax |
push ecx |
cmp ecx, eax |
jb @f |
mov ecx, eax |
@@: |
mov [esp+10h+4], ecx |
mov edi, edx |
rep movsb |
mov edx, edi |
pop ecx |
sub ecx, [esp+10h] |
jnz @f |
.retok: |
popad |
xor eax, eax |
ret |
@@: |
cmp [ntfs_cur_read], 0x200 |
jz .alignedstart |
.eof_ebx: |
popad |
jmp .eof |
.alignedstart: |
mov eax, [ebx] |
push edx |
mov edx, [ebx+4] |
add eax, 511 |
adc edx, 0 |
shrd eax, edx, 9 |
pop edx |
.zero1: |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_buf], edx |
mov eax, ecx |
shr eax, 9 |
mov [ntfs_cur_size], eax |
add eax, [ntfs_cur_offs] |
push eax |
call ntfs_read_attr.continue |
pop [ntfs_cur_offs] |
mov eax, [ntfs_cur_read] |
add [esp+10h], eax |
mov eax, ecx |
and eax, not 0x1FF |
cmp [ntfs_cur_read], eax |
jnz .eof_ebx |
and ecx, 0x1FF |
jz .retok |
add edx, [ntfs_cur_read] |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
call ntfs_read_attr.continue |
cmp [ntfs_cur_read], ecx |
jb @f |
mov [ntfs_cur_read], ecx |
@@: |
xchg ecx, [ntfs_cur_read] |
push ecx |
mov edi, edx |
mov esi, ntfs_bitmap_buf |
add [esp+10h+4], ecx |
rep movsb |
pop ecx |
xor eax, eax |
cmp ecx, [ntfs_cur_read] |
jz @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [esp+1Ch], eax |
popad |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdReadFolder - read NTFS hard disk folder |
; |
; esi points to filename |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdReadFolder: |
mov eax, 5 ; root cluster |
cmp byte [esi], 0 |
jz .doit |
call ntfs_find_lfn |
jnc .doit2 |
.notfound: |
or ebx, -1 |
push ERROR_FILE_NOT_FOUND |
.pop_ret: |
pop eax |
ret |
.doit: |
mov [ntfs_cur_iRecord], eax |
.doit2: |
mov [ntfs_cur_attr], 0x10 ; $STANDARD_INFORMATION |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
call ntfs_read_attr |
jc .notfound |
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT |
and [ntfs_cur_offs], 0 |
mov eax, [ntfs_data.cur_index_size] |
mov [ntfs_cur_size], eax |
mov eax, [ntfs_data.cur_index_buf] |
mov [ntfs_cur_buf], eax |
call ntfs_read_attr |
jnc .ok |
cmp [hd_error], 0 |
jz .notfound |
or ebx, -1 |
push 11 |
jmp .pop_ret |
.ok: |
cmp [ntfs_cur_read], 0x20 |
jae @f |
or ebx, -1 |
.fserr: |
push ERROR_FAT_TABLE |
jmp .pop_ret |
@@: |
pushad |
mov esi, [ntfs_data.cur_index_buf] |
mov eax, [esi+14h] |
add eax, 10h |
cmp [ntfs_cur_read], eax |
jae .readok1 |
add eax, 1FFh |
shr eax, 9 |
cmp eax, [ntfs_data.cur_index_size] |
ja @f |
popad |
jmp .fserr |
@@: |
; reallocate |
push eax |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop eax |
mov [ntfs_data.cur_index_size], eax |
push eax |
call kernel_alloc |
test eax, eax |
jnz @f |
and [ntfs_data.cur_index_size], 0 |
and [ntfs_data.cur_index_buf], 0 |
.nomem: |
popad |
or ebx, -1 |
push 12 |
pop eax |
ret |
@@: |
mov [ntfs_data.cur_index_buf], eax |
popad |
jmp .doit2 |
.readok1: |
mov ebp, [esi+8] ; subnode_size |
shr ebp, 9 |
cmp ebp, [ntfs_data.cur_index_size] |
jbe .ok2 |
push esi ebp |
push ebp |
call kernel_alloc |
pop ebp esi |
test eax, eax |
jz .nomem |
mov edi, eax |
mov ecx, [ntfs_data.cur_index_size] |
shl ecx, 9-2 |
rep movsd |
mov esi, eax |
mov [ntfs_data.cur_index_size], ebp |
push esi ebp |
push [ntfs_data.cur_index_buf] |
call kernel_free |
pop ebp esi |
mov [ntfs_data.cur_index_buf], esi |
.ok2: |
add esi, 10h |
mov ebx, [esp+10h] |
mov edx, [esp+14h] |
push dword [ebx+4] ; read ANSI/UNICODE name |
mov ebx, [ebx] |
; init header |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
mov byte [edx], 1 ; version |
mov ecx, [esp+4+18h] |
push edx |
mov edx, esp |
; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block, |
; ecx = number of blocks to read |
; edx -> parameters block: dd <output>, dd <flags> |
cmp [ntfs_cur_iRecord], 5 |
jz .skip_specials |
; dot and dotdot entries |
push esi |
xor esi, esi |
call .add_special_entry |
inc esi |
call .add_special_entry |
pop esi |
.skip_specials: |
; at first, dump index root |
add esi, [esi] |
.dump_root: |
test byte [esi+0Ch], 2 |
jnz .dump_root_done |
call .add_entry |
movzx eax, word [esi+8] |
add esi, eax |
jmp .dump_root |
.dump_root_done: |
; now dump all subnodes |
push ecx edi |
mov edi, ntfs_bitmap_buf |
mov [ntfs_cur_buf], edi |
mov ecx, 0x400/4 |
xor eax, eax |
rep stosd |
mov [ntfs_cur_attr], 0xB0 ; $BITMAP |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 2 |
call ntfs_read_attr |
pop edi ecx |
push 0 ; save offset in $BITMAP attribute |
and [ntfs_cur_offs], 0 |
.dumploop: |
mov [ntfs_cur_attr], 0xA0 |
mov [ntfs_cur_size], ebp |
mov eax, [ntfs_data.cur_index_buf] |
mov esi, eax |
mov [ntfs_cur_buf], eax |
push [ntfs_cur_offs] |
mov eax, [ntfs_cur_offs] |
imul eax, ebp |
mov [ntfs_cur_offs], eax |
call ntfs_read_attr |
pop [ntfs_cur_offs] |
mov eax, ebp |
shl eax, 9 |
cmp [ntfs_cur_read], eax |
jnz .done |
push eax |
mov eax, [ntfs_cur_offs] |
and eax, 0x400*8-1 |
bt dword [ntfs_bitmap_buf], eax |
pop eax |
jnc .dump_subnode_done |
cmp dword [esi], 'INDX' |
jnz .dump_subnode_done |
push ebx |
mov ebx, esi |
call ntfs_restore_usa |
pop ebx |
jc .dump_subnode_done |
add esi, 0x18 |
add esi, [esi] |
.dump_subnode: |
test byte [esi+0Ch], 2 |
jnz .dump_subnode_done |
call .add_entry |
movzx eax, word [esi+8] |
add esi, eax |
jmp .dump_subnode |
.dump_subnode_done: |
inc [ntfs_cur_offs] |
test [ntfs_cur_offs], 0x400*8-1 |
jnz .dumploop |
mov [ntfs_cur_attr], 0xB0 |
push ecx edi |
mov edi, ntfs_bitmap_buf |
mov [ntfs_cur_buf], edi |
mov ecx, 0x400/4 |
xor eax, eax |
rep stosd |
pop edi ecx |
pop eax |
push [ntfs_cur_offs] |
inc eax |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_size], 2 |
push eax |
call ntfs_read_attr |
pop eax |
pop [ntfs_cur_offs] |
push eax |
jmp .dumploop |
.done: |
pop eax |
pop edx |
mov ebx, [edx+4] |
pop edx |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [esp+1Ch], eax |
mov [esp+10h], ebx |
popad |
ret |
.add_special_entry: |
mov eax, [edx] |
inc dword [eax+8] ; new file found |
dec ebx |
jns .ret |
dec ecx |
js .ret |
inc dword [eax+4] ; new file block copied |
mov eax, [edx+4] |
mov [edi+4], eax |
; mov eax, dword [ntfs_bitmap_buf+0x20] |
; or al, 0x10 |
mov eax, 0x10 |
stosd |
scasd |
push edx |
mov eax, dword [ntfs_bitmap_buf] |
mov edx, dword [ntfs_bitmap_buf+4] |
call ntfs_datetime_to_bdfe |
mov eax, dword [ntfs_bitmap_buf+0x18] |
mov edx, dword [ntfs_bitmap_buf+0x1C] |
call ntfs_datetime_to_bdfe |
mov eax, dword [ntfs_bitmap_buf+8] |
mov edx, dword [ntfs_bitmap_buf+0xC] |
call ntfs_datetime_to_bdfe |
pop edx |
xor eax, eax |
stosd |
stosd |
mov al, '.' |
push edi ecx |
lea ecx, [esi+1] |
test byte [edi-0x24], 1 |
jz @f |
rep stosw |
pop ecx |
xor eax, eax |
stosw |
pop edi |
add edi, 520 |
ret |
@@: |
rep stosb |
pop ecx |
xor eax, eax |
stosb |
pop edi |
add edi, 264 |
.ret: |
ret |
.add_entry: |
; do not return DOS 8.3 names |
cmp byte [esi+0x51], 2 |
jz .ret |
; do not return system files |
; ... note that there will be no bad effects if system files also were reported ... |
cmp dword [esi], 0x10 |
jb .ret |
mov eax, [edx] |
inc dword [eax+8] ; new file found |
dec ebx |
jns .ret |
dec ecx |
js .ret |
inc dword [eax+4] ; new file block copied |
mov eax, [edx+4] ; flags |
call ntfs_direntry_to_bdfe |
push ecx esi edi |
movzx ecx, byte [esi+0x50] |
add esi, 0x52 |
test byte [edi-0x24], 1 |
jz .ansi |
shr ecx, 1 |
rep movsd |
adc ecx, ecx |
rep movsw |
and word [edi], 0 |
pop edi |
add edi, 520 |
pop esi ecx |
ret |
.ansi: |
jecxz .skip |
@@: |
lodsw |
call uni2ansi_char |
stosb |
loop @b |
.skip: |
xor al, al |
stosb |
pop edi |
add edi, 264 |
pop esi ecx |
ret |
ntfs_direntry_to_bdfe: |
mov [edi+4], eax ; ANSI/UNICODE name |
mov eax, [esi+48h] |
test eax, 0x10000000 |
jz @f |
and eax, not 0x10000000 |
or al, 0x10 |
@@: |
stosd |
scasd |
push edx |
mov eax, [esi+0x18] |
mov edx, [esi+0x1C] |
call ntfs_datetime_to_bdfe |
mov eax, [esi+0x30] |
mov edx, [esi+0x34] |
call ntfs_datetime_to_bdfe |
mov eax, [esi+0x20] |
mov edx, [esi+0x24] |
call ntfs_datetime_to_bdfe |
pop edx |
mov eax, [esi+0x40] |
stosd |
mov eax, [esi+0x44] |
stosd |
ret |
iglobal |
_24 dd 24 |
_60 dd 60 |
_10000000 dd 10000000 |
days400year dd 365*400+100-4+1 |
days100year dd 365*100+25-1 |
days4year dd 365*4+1 |
days1year dd 365 |
months dd 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 |
months2 dd 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 |
_400 dd 400 |
_100 dd 100 |
endg |
ntfs_datetime_to_bdfe: |
; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC |
push eax |
mov eax, edx |
xor edx, edx |
div [_10000000] |
xchg eax, [esp] |
div [_10000000] |
pop edx |
.sec: |
; edx:eax = number of seconds since January 1, 1601 |
push eax |
mov eax, edx |
xor edx, edx |
div [_60] |
xchg eax, [esp] |
div [_60] |
mov [edi], dl |
pop edx |
; edx:eax = number of minutes |
div [_60] |
mov [edi+1], dl |
; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32) |
xor edx, edx |
div [_24] |
mov [edi+2], dl |
mov [edi+3], byte 0 |
; eax = number of days since January 1, 1601 |
xor edx, edx |
div [days400year] |
imul eax, 400 |
add eax, 1601 |
mov [edi+6], ax |
mov eax, edx |
xor edx, edx |
div [days100year] |
cmp al, 4 |
jnz @f |
dec eax |
add edx, [days100year] |
@@: |
imul eax, 100 |
add [edi+6], ax |
mov eax, edx |
xor edx, edx |
div [days4year] |
shl eax, 2 |
add [edi+6], ax |
mov eax, edx |
xor edx, edx |
div [days1year] |
cmp al, 4 |
jnz @f |
dec eax |
add edx, [days1year] |
@@: |
add [edi+6], ax |
push esi edx |
mov esi, months |
movzx eax, word [edi+6] |
test al, 3 |
jnz .noleap |
xor edx, edx |
push eax |
div [_400] |
pop eax |
test edx, edx |
jz .leap |
xor edx, edx |
div [_100] |
test edx, edx |
jz .noleap |
.leap: |
mov esi, months2 |
.noleap: |
pop edx |
xor eax, eax |
inc eax |
@@: |
sub edx, [esi] |
jb @f |
add esi, 4 |
inc eax |
jmp @b |
@@: |
add edx, [esi] |
pop esi |
inc edx |
mov [edi+4], dl |
mov [edi+5], al |
add edi, 8 |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdRewrite - write to NTFS hard disk |
; |
; esi points to filename |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdRewrite: |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdWrite - write to NTFS hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdWrite: |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdSetFileEnd - set end of file on NTFS hard disk |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdSetFileEnd: |
ntfs_HdSetFileInfo: |
;---------------------------------------------------------------- |
; |
; ntfs_HdDelete - delete file or empty folder from NTFS hard disk |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdDelete: |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
ntfs_HdGetFileInfo: |
cmp byte [esi], 0 |
jnz @f |
push 2 |
pop eax |
ret |
@@: |
call ntfs_find_lfn |
jnc .doit |
push ERROR_FILE_NOT_FOUND |
pop eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
.doit: |
push esi edi |
mov esi, eax |
mov edi, edx |
xor eax, eax |
call ntfs_direntry_to_bdfe |
pop edi esi |
xor eax, eax |
ret |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/fs/ext2.inc |
---|
0,0 → 1,1318 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; 02.02.2010 turbanoff - support 70.5 ;; |
;; 23.01.2010 turbanoff - support 70.0 70.1 ;; |
;; ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
EXT2_BAD_INO = 1 |
EXT2_ROOT_INO = 2 |
EXT2_ACL_IDX_INO = 3 |
EXT2_ACL_DATA_INO = 4 |
EXT2_BOOT_LOADER_INO= 5 |
EXT2_UNDEL_DIR_INO = 6 |
;type inode |
EXT2_S_IFREG = 0x8000 |
EXT2_S_IFDIR = 0x4000 |
;user inode right's |
EXT2_S_IRUSR = 0x0100 |
EXT2_S_IWUSR = 0x0080 |
EXT2_S_IXUSR = 0x0040 |
;group inode right's |
EXT2_S_IRGRP = 0x0020 |
EXT2_S_IWGRP = 0x0010 |
EXT2_S_IXGRP = 0x0008 |
;other inode right's |
EXT2_S_IROTH = 0x0004 |
EXT2_S_IWOTH = 0x0002 |
EXT2_S_IXOTH = 0x0001 |
EXT2_777_MODE = EXT2_S_IROTH or EXT2_S_IWOTH or EXT2_S_IXOTH or \ |
EXT2_S_IRGRP or EXT2_S_IWGRP or EXT2_S_IXGRP or \ |
EXT2_S_IRUSR or EXT2_S_IWUSR or EXT2_S_IXUSR |
EXT2_FT_REG_FILE = 1 ;это файл, запись в родительском каталоге |
EXT2_FT_DIR = 2 ;это папка |
FS_FT_HIDDEN = 2 |
FS_FT_DIR = 0x10 ;это папка |
FS_FT_ASCII = 0 ;имя в ascii |
FS_FT_UNICODE = 1 ;имя в unicode |
EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 |
uglobal |
EXT2_files_in_folder dd ? ;всего файлов в папке |
EXT2_read_in_folder dd ? ;сколько файлов "считали" |
EXT2_end_block dd ? ;конец очередного блока папки |
EXT2_counter_blocks dd ? |
EXT2_filename db 256 dup ? |
EXT2_parent_name db 256 dup ? |
EXT2_name_len dd ? |
endg |
struct EXT2_INODE_STRUC |
.i_mode dw ? |
.i_uid dw ? |
.i_size dd ? |
.i_atime dd ? |
.i_ctime dd ? |
.i_mtime dd ? |
.i_dtime dd ? |
.i_gid dw ? |
.i_links_count dw ? |
.i_blocks dd ? |
.i_flags dd ? |
.i_osd1 dd ? |
.i_block dd 15 dup ? |
.i_generation dd ? |
.i_file_acl dd ? |
.i_dir_acl dd ? |
.i_faddr dd ? |
.i_osd2 dd ? ; 1..12 |
ends |
struct EXT2_DIR_STRUC |
.inode dd ? |
.rec_len dw ? |
.name_len db ? |
.file_type db ? |
.name db ? ; 0..255 |
ends |
struct EXT2_BLOCK_GROUP_DESC |
.block_bitmap dd ? |
.inode_bitmap dd ? |
.inode_table dd ? |
.free_blocks_count dw ? |
.free_inodes_count dw ? |
.used_dirs_count dw ? |
ends |
struct EXT2_SB_STRUC |
.inodes_count dd ? ;+0 |
.blocks_count dd ? ;+4 |
.r_block_count dd ? ;+8 |
.free_block_count dd ? ;+12 |
.free_inodes_count dd ? ;+16 |
.first_data_block dd ? ;+20 |
.log_block_size dd ? ;+24 |
.log_frag_size dd ? ;+28 |
.blocks_per_group dd ? ;+32 |
.frags_per_group dd ? ;+36 |
.inodes_per_group dd ? ;+40 |
.mtime dd ? ;+44 |
.wtime dd ? ;+48 |
.mnt_count dw ? ;+52 |
.max_mnt_count dw ? ;+54 |
.magic dw ? ;+56 |
.state dw ? ;+58 |
.errors dw ? ;+60 |
.minor_rev_level dw ? ;+62 |
.lastcheck dd ? ;+64 |
.check_intervals dd ? ;+68 |
.creator_os dd ? ;+72 |
.rev_level dd ? ;+76 |
.def_resuid dw ? ;+80 |
.def_resgid dw ? ;+82 |
.first_ino dd ? ;+84 |
.inode_size dw ? ;+88 |
.block_group_nr dw ? ;+90 |
.feature_compat dd ? ;+92 |
.feature_incompat dd ? ;+96 |
.feature_ro_compat dd ? ;+100 |
.uuid db 16 dup ? ;+104 |
.volume_name db 16 dup ? ;+120 |
.last_mounted db 64 dup ? ;+136 |
.algo_bitmap dd ? ;+200 |
.prealloc_blocks db ? ;+204 |
.preallock_dir_blocks db ? ;+205 |
dw ? ;+206 alignment |
.journal_uuid db 16 dup ? ;+208 |
.journal_inum dd ? ;+224 |
.journal_dev dd ? ;+228 |
.last_orphan dd ? ;+232 |
.hash_seed dd 4 dup ? ;+236 |
.def_hash_version db ? ;+252 |
db 3 dup ? ;+253 reserved |
.default_mount_options dd ? ;+256 |
.first_meta_bg dd ? ;+260 |
ends |
ext2_test_superblock: |
cmp [fs_type], 0x83 |
jne .no |
mov eax, [PARTITION_START] |
add eax, 2 ;superblock start at 1024b |
call hd_read |
cmp dword [ebx+24], 3 ;s_block_size 0,1,2,3 |
ja .no |
cmp word [ebx+56], 0xEF53 ;s_magic |
jne .no |
cmp word [ebx+58], 1 ;s_state (EXT_VALID_FS=1) |
jne .no |
mov eax, [ebx+96] |
test eax, EXT2_FEATURE_INCOMPAT_FILETYPE |
jz .no |
test eax, not EXT2_FEATURE_INCOMPAT_FILETYPE |
jnz .no |
; OK, this is correct EXT2 superblock |
clc |
ret |
.no: |
; No, this superblock isn't EXT2 |
stc |
ret |
ext2_setup: |
mov [fs_type], 2 |
push 512 |
call kernel_alloc ; mem for superblock |
mov esi, ebx |
mov edi, eax |
mov ecx, 512/4 |
rep movsd ; copy sb to reserved mem |
mov ebx, eax |
mov [ext2_data.sb],eax |
mov eax, [ebx + EXT2_SB_STRUC.blocks_count] |
sub eax, [ebx + EXT2_SB_STRUC.first_data_block] |
dec eax |
xor edx, edx |
div [ebx + EXT2_SB_STRUC.blocks_per_group] |
inc eax |
mov [ext2_data.groups_count], eax |
mov ecx, [ebx+24] |
inc ecx |
mov [ext2_data.log_block_size], ecx ; 1, 2, 3, 4 equ 1kb, 2kb, 4kb, 8kb |
mov eax, 1 |
shl eax, cl |
mov [ext2_data.count_block_in_block], eax |
shl eax, 7 |
mov [ext2_data.count_pointer_in_block], eax |
mov edx, eax ; потом еще квадрат найдем |
shl eax, 2 |
mov [ext2_data.block_size], eax |
push eax eax ; 2 kernel_alloc |
mov eax, edx |
mul edx |
mov [ext2_data.count_pointer_in_block_square], eax |
call kernel_alloc |
mov [ext2_data.ext2_save_block], eax ; and for temp block |
call kernel_alloc |
mov [ext2_data.ext2_temp_block], eax ; and for get_inode proc |
movzx ebp, word [ebx+88] |
mov ecx, [ebx+32] |
mov edx, [ebx+40] |
mov [ext2_data.inode_size], ebp |
mov [ext2_data.blocks_per_group], ecx |
mov [ext2_data.inodes_per_group], edx |
push ebp ebp ebp ;3 kernel_alloc |
call kernel_alloc |
mov [ext2_data.ext2_save_inode], eax |
call kernel_alloc |
mov [ext2_data.ext2_temp_inode], eax |
call kernel_alloc |
mov [ext2_data.root_inode], eax |
mov ebx, eax |
mov eax, EXT2_ROOT_INO |
call ext2_get_inode ; read root inode |
jmp return_from_part_set |
;================================================================== |
;in: eax = i_block |
; ebx = pointer to return memory |
ext2_get_block: |
push eax ebx ecx |
mov ecx, [ext2_data.log_block_size] |
shl eax, cl |
add eax, [PARTITION_START] |
mov ecx, [ext2_data.count_block_in_block] |
@@: |
call hd_read |
inc eax |
add ebx, 512 |
loop @B |
pop ecx ebx eax |
ret |
;=================================================================== |
; in: ecx = номер блока в inode (0..) |
; ebp = адрес inode |
; out: ecx = адрес очередного блока |
ext2_get_inode_block: |
cmp ecx, 12 ; 0..11 - direct block address |
jb .get_direct_block |
sub ecx, 12 |
cmp ecx, [ext2_data.count_pointer_in_block] ; 12.. - indirect block |
jb .get_indirect_block |
sub ecx, [ext2_data.count_pointer_in_block] |
cmp ecx, [ext2_data.count_pointer_in_block_square] |
jb .get_double_indirect_block |
sub ecx, [ext2_data.count_pointer_in_block_square] |
;.get_triple_indirect_block: |
push eax edx ebx |
mov eax, [ebx + EXT2_INODE_STRUC.i_block + 14*4] |
mov ebx, [ext2_data.ext2_temp_block] |
call ext2_get_block |
xor edx, edx |
mov eax, ecx |
div [ext2_data.count_pointer_in_block_square] |
;eax - номер в полученном блоке edx - номер дальше |
mov eax, [ebx + eax*4] |
call ext2_get_block |
mov eax, edx |
jmp @F |
.get_double_indirect_block: |
push eax edx ebx |
mov eax, [ebp + EXT2_INODE_STRUC.i_block + 13*4] |
mov ebx, [ext2_data.ext2_temp_block] |
call ext2_get_block |
mov eax, ecx |
@@: |
xor edx, edx |
div [ext2_data.count_pointer_in_block] |
mov eax, [ebx + eax*4] |
call ext2_get_block |
mov ecx, [ebx + edx*4] |
pop ebx edx eax |
ret |
.get_indirect_block: |
push eax ebx |
mov eax, [ebp + EXT2_INODE_STRUC.i_block + 12*4] |
mov ebx, [ext2_data.ext2_temp_block] |
call ext2_get_block |
mov ecx, [ebx + ecx*4] |
pop ebx eax |
ret |
.get_direct_block: |
mov ecx, dword [ebp + EXT2_INODE_STRUC.i_block + ecx*4] |
ret |
;=================================================================== |
;get content inode by num |
;in: eax = inode_num |
; ebx = address of inode content |
ext2_get_inode: |
pushad |
mov edi, ebx ;сохраним адрес inode |
dec eax |
xor edx, edx |
div [ext2_data.inodes_per_group] |
push edx ;locale num in group |
mov edx, 32 |
mul edx ; address block_group in global_desc_table |
; в eax - смещение группы с inode-ом относительно начала глобальной дескрипторной таблицы |
; найдем блок в котором он находится |
div [ext2_data.block_size] |
mov ecx, [ext2_data.sb] |
add eax, [ecx + EXT2_SB_STRUC.first_data_block] |
inc eax |
mov ebx, [ext2_data.ext2_temp_block] |
call ext2_get_block |
add ebx, edx ; локальный номер в блоке |
mov eax, [ebx+8] ; номер блока - в терминах ext2 |
mov ecx, [ext2_data.log_block_size] |
shl eax, cl |
add eax, [PARTITION_START] ; а старт раздела - в терминах hdd (512) |
;eax - указывает на таблицу inode-ов на hdd |
mov esi, eax ;сохраним его пока в esi |
; прибавим локальный адрес inode-а |
pop eax ; index |
mov ecx, [ext2_data.inode_size] |
mul ecx ; (index * inode_size) |
mov ebp, 512 |
div ebp ;поделим на размер блока |
add eax, esi ;нашли адрес блока для чтения |
mov ebx, [ext2_data.ext2_temp_block] |
call hd_read |
mov esi, edx ;добавим "остаток" |
add esi, ebx ;к адресу |
; mov ecx, [ext2_data.inode_size] |
rep movsb ;копируем inode |
popad |
ret |
;---------------------------------------------------------------- |
; in: esi -> children |
; ebx -> pointer to dir block |
; out: esi -> name without parent or not_changed |
; ebx -> dir_rec of inode children or trash |
ext2_test_block_by_name: |
push eax ecx edx edi |
mov edx, ebx |
add edx, [ext2_data.block_size] ;запомним конец блока |
.start_rec: |
cmp [ebx + EXT2_DIR_STRUC.inode], 0 |
jz .next_rec |
push esi |
movzx ecx, [ebx + EXT2_DIR_STRUC.name_len] |
mov edi, EXT2_filename |
lea esi, [ebx + EXT2_DIR_STRUC.name] |
call utf8toansi_str |
mov ecx, edi |
sub ecx, EXT2_filename ;кол-во байт в получившейся строке |
mov edi, EXT2_filename |
mov esi, [esp] |
@@: |
jecxz .test_find |
dec ecx |
lodsb |
call char_toupper |
mov ah, [edi] |
inc edi |
xchg al, ah |
call char_toupper |
cmp al, ah |
je @B |
@@: ;не подошло |
pop esi |
.next_rec: |
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] |
add ebx, eax ;к след. записи |
cmp ebx, edx ;проверим конец ли |
jb .start_rec |
jmp .ret |
.test_find: |
cmp byte [esi], 0 |
je .find ;нашли конец |
cmp byte [esi], '/' |
jne @B |
inc esi |
.find: |
pop eax ;удаляем из стека сохраненое значение |
.ret: |
pop edi edx ecx eax |
ret |
;---------------------------------------------------------------- |
; |
; ext2_HdReadFolder - read disk folder |
; |
; esi points to filename |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ext2_HdReadFolder: |
cmp byte [esi], 0 |
jz .doit |
push ecx ebx |
call ext2_find_lfn |
jnc .doit2 |
pop ebx |
.not_found: |
pop ecx |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.doit: |
mov ebp, [ext2_data.root_inode] |
push ecx |
jmp @F |
.doit2: |
pop ebx |
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
jz .not_found |
@@: |
xor eax, eax |
mov edi, edx |
mov ecx, 32/4 |
rep stosd ; fill header zero |
pop edi ; edi = число блоков для чтения |
push edx ebx |
;--------------------------------------------- final step |
and [EXT2_read_in_folder], 0 |
and [EXT2_files_in_folder], 0 |
mov eax, [ebp + EXT2_INODE_STRUC.i_blocks] |
mov [EXT2_counter_blocks], eax |
add edx, 32 ; (header pointer in stack) edx = current mem for return |
xor esi, esi ; esi = номер блока по порядку |
.new_block_folder: ;reserved label |
mov ecx, esi ; получим номер блока |
call ext2_get_inode_block |
mov eax, ecx |
mov ebx, [ext2_data.ext2_save_block] |
call ext2_get_block ; и считываем блок с hdd |
mov eax, ebx ; eax = current dir record |
add ebx, [ext2_data.block_size] |
mov [EXT2_end_block], ebx ; запомним конец очередного блока |
pop ecx |
mov ecx, [ecx] ; ecx = first wanted (flags ommited) |
.find_wanted_start: |
jecxz .find_wanted_end |
.find_wanted_cycle: |
cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
jz @F |
inc [EXT2_files_in_folder] |
dec ecx |
@@: |
movzx ebx, [eax+EXT2_DIR_STRUC.rec_len] |
cmp ebx, 12 ; минимальная длина записи |
jb .end_error |
test ebx, 0x3 ; длина записи должна делиться на 4 |
jnz .end_error |
add eax, ebx ; к следующей записи |
cmp eax, [EXT2_end_block] ; проверяем "конец" |
jb .find_wanted_start |
push .find_wanted_start |
.end_block: ;вылетили из цикла |
mov ebx, [ext2_data.count_block_in_block] |
sub [EXT2_counter_blocks], ebx |
jbe .end_dir |
inc esi ;получаем новый блок |
push ecx |
mov ecx, esi |
call ext2_get_inode_block |
mov eax, ecx |
mov ebx, [ext2_data.ext2_save_block] |
call ext2_get_block |
pop ecx |
mov eax, ebx |
add ebx, [ext2_data.block_size] |
mov [EXT2_end_block], ebx |
ret ; опять в цикл |
.wanted_end: |
loop .find_wanted_cycle ; ecx = -1 |
.find_wanted_end: |
mov ecx, edi |
.wanted_start: ; ищем first_wanted+count |
jecxz .wanted_end |
cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
jz .empty_rec |
inc [EXT2_files_in_folder] |
inc [EXT2_read_in_folder] |
mov edi, edx |
push eax ecx |
xor eax, eax |
mov ecx, 40 / 4 |
rep stosd |
pop ecx eax |
push eax esi edx ;получим inode |
mov eax, [eax + EXT2_DIR_STRUC.inode] |
mov ebx, [ext2_data.ext2_temp_inode] |
call ext2_get_inode |
lea edi, [edx + 8] |
mov eax, [ebx + EXT2_INODE_STRUC.i_ctime] ; переведем время в ntfs формат |
xor edx, edx |
add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
mov eax, [ebx + EXT2_INODE_STRUC.i_atime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
mov eax, [ebx + EXT2_INODE_STRUC.i_mtime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
pop edx ; пока достаем только буфер |
test [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR ; для папки размер |
jnz @F ; не возвращаем |
mov eax, [ebx + EXT2_INODE_STRUC.i_size] ;low size |
stosd |
mov eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ;high size |
stosd |
xor dword [edx], FS_FT_DIR |
@@: |
xor dword [edx], FS_FT_DIR |
pop esi eax |
or dword [edx+4], FS_FT_ASCII ; symbol type in name |
;теперь скопируем имя, сконвертировав из UTF-8 в CP866 |
push eax ecx esi |
movzx ecx, [eax + EXT2_DIR_STRUC.name_len] |
lea edi, [edx + 40] |
lea esi, [eax + EXT2_DIR_STRUC.name] |
call utf8toansi_str |
pop esi ecx eax |
and byte [edi], 0 |
cmp byte [edx + 40], '.' |
jne @F |
or dword [edx], FS_FT_HIDDEN |
@@: |
add edx, 40 + 264 ; go to next record |
dec ecx ; если запись пустая ecx не надо уменьшать |
.empty_rec: |
movzx ebx, [eax + EXT2_DIR_STRUC.rec_len] |
cmp ebx, 12 ; минимальная длина записи |
jb .end_error |
test ebx, 0x3 ; длина записи должна делиться на 4 |
jnz .end_error |
add eax, ebx |
cmp eax, [EXT2_end_block] |
jb .wanted_start |
push .wanted_start ; дошли до конца очередного блока |
jmp .end_block |
.end_dir: |
pop eax ; мусор (адрес возврата в цикл) |
.end_error: |
pop edx |
mov ebx, [EXT2_read_in_folder] |
mov ecx, [EXT2_files_in_folder] |
mov dword [edx], 1 ;version |
xor eax, eax |
mov [edx+4], ebx |
mov [edx+8], ecx |
lea edi, [edx + 12] |
mov ecx, 20 / 4 |
rep stosd |
ret |
;====================== end ext2_HdReadFolder |
utf8toansi_str: |
; convert UTF-8 string to ASCII-string (codepage 866) |
; in: ecx=length source, esi->source, edi->buffer |
; destroys: eax,esi,edi |
jecxz .ret |
.start: |
lodsw |
cmp al, 0x80 |
jb .ascii |
xchg al, ah ; big-endian |
cmp ax, 0xd080 |
jz .yo1 |
cmp ax, 0xd191 |
jz .yo2 |
cmp ax, 0xd090 |
jb .unk |
cmp ax, 0xd180 |
jb .rus1 |
cmp ax, 0xd190 |
jb .rus2 |
.unk: |
mov al, '_' |
jmp .doit |
.yo1: |
mov al, 0xf0 ; Ё capital |
jmp .doit |
.yo2: |
mov al, 0xf1 ; ё small |
jmp .doit |
.rus1: |
sub ax, 0xd090 - 0x80 |
jmp .doit |
.rus2: |
sub ax, 0xd18f - 0xEF |
.doit: |
stosb |
sub ecx, 2 |
ja .start |
ret |
.ascii: |
stosb |
dec esi |
dec ecx |
jnz .start |
.ret: |
ret |
;---------------------------------------------------------------- |
; |
; ext2_HdRead - read hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ext2_HdRead: |
cmp byte [esi], 0 |
jnz @F |
.this_is_nofile: |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
@@: |
push ecx ebx |
call ext2_find_lfn |
pop ebx ecx |
jnc .doit |
;.not_found: |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.doit: |
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG |
jz .this_is_nofile |
;-----------------------------------------------------------------------------final step |
mov edi, edx ; edi = pointer to return mem |
mov esi, ebx ; esi = pointer to first_wanted |
;///// сравним хватит ли нам файла или нет |
mov ebx, [esi+4] |
mov eax, [esi] ; ebx : eax - стартовый номер байта |
cmp [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx |
ja .size_great |
jb .size_less |
cmp [ebp + EXT2_INODE_STRUC.i_size], eax |
ja .size_great |
.size_less: |
xor ebx, ebx |
mov eax, ERROR_END_OF_FILE |
ret |
.size_great: |
add eax, ecx ;add to first_wanted кол-во байт для чтения |
adc ebx, 0 |
cmp [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx |
ja .size_great_great |
jb .size_great_less |
cmp [ebp + EXT2_INODE_STRUC.i_size], eax |
jae .size_great_great ; а если равно, то не важно куда |
.size_great_less: |
or [EXT2_files_in_folder], 1 ;читаем по границе размера |
mov ecx, [ebp + EXT2_INODE_STRUC.i_size] |
sub ecx, [esi] ;(размер - старт) |
jmp @F |
.size_great_great: |
and [EXT2_files_in_folder], 0 ;читаем столько сколько запросили |
@@: |
push ecx ;save for return |
test esi, esi |
jz .zero_start |
;пока делаем п..ц криво =) |
mov edx, [esi+4] |
mov eax, [esi] |
div [ext2_data.block_size] |
mov [EXT2_counter_blocks], eax ;номер блока запоминаем |
push ecx |
mov ecx, eax |
call ext2_get_inode_block |
mov ebx, [ext2_data.ext2_save_block] |
mov eax, ecx |
call ext2_get_block |
pop ecx |
add ebx, edx |
neg edx |
add edx,[ext2_data.block_size] ;block_size - стартовый байт = сколько байт 1-го блока |
cmp ecx, edx |
jbe .only_one_block |
mov eax, ecx |
sub eax, edx |
mov ecx, edx |
mov esi, ebx |
rep movsb ;кусок 1-го блока |
jmp @F |
.zero_start: |
mov eax, ecx |
;теперь в eax кол-во оставшихся байт для чтения |
@@: |
mov ebx, edi ;чтение блока прям в ->ebx |
xor edx, edx |
div [ext2_data.block_size] ;кол-во байт в последнем блоке (остаток) в edx |
mov edi, eax ;кол-во целых блоков в edi |
@@: |
test edi, edi |
jz .finish_block |
inc [EXT2_counter_blocks] |
mov ecx, [EXT2_counter_blocks] |
call ext2_get_inode_block |
mov eax, ecx ;а ebx уже забит нужным значением |
call ext2_get_block |
add ebx, [ext2_data.block_size] |
dec edi |
jmp @B |
.finish_block: ;в edx - кол-во байт в последнем блоке |
test edx, edx |
jz .end_read |
mov ecx, [EXT2_counter_blocks] |
inc ecx |
call ext2_get_inode_block |
mov edi, ebx |
mov eax, ecx |
mov ebx, [ext2_data.ext2_save_block] |
call ext2_get_block |
mov ecx, edx |
.only_one_block: |
mov esi, ebx |
rep movsb ;кусок last блока |
.end_read: |
pop ebx |
cmp [EXT2_files_in_folder], 0 |
jz @F |
mov eax, ERROR_END_OF_FILE |
ret |
@@: |
xor eax, eax |
ret |
;======================== |
;in : esi -> name not save: eax ebx ecx |
;out: ebp -> inode cf=0 |
; ebp -> trash cf=1 |
ext2_find_lfn: |
mov ebp, [ext2_data.root_inode] |
.next_folder: |
or [EXT2_counter_blocks], -1 ;счетчик блоков папки cur block of inode |
mov eax, [ebp + EXT2_INODE_STRUC.i_blocks] ;убывающий счетчик блоков |
add eax, [ext2_data.count_block_in_block] |
mov [EXT2_end_block], eax |
.next_block_folder: |
mov eax, [ext2_data.count_block_in_block] |
sub [EXT2_end_block], eax |
jz .not_found |
inc [EXT2_counter_blocks] |
mov ecx, [EXT2_counter_blocks] |
call ext2_get_inode_block |
mov eax, ecx |
mov ebx, [ext2_data.ext2_save_block] ;ebx = cur dir record |
call ext2_get_block |
mov eax, esi |
call ext2_test_block_by_name |
cmp eax, esi ;нашли имя? |
jz .next_block_folder |
cmp byte [esi],0 |
jz .get_inode_ret |
cmp [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR |
jne .not_found ;нашли, но это не папка |
mov eax, [ebx + EXT2_DIR_STRUC.inode] |
mov ebx, [ext2_data.ext2_save_inode] ;все же папка. |
call ext2_get_inode |
mov ebp, ebx |
jmp .next_folder |
.not_found: |
stc |
ret |
.get_inode_ret: |
mov [EXT2_end_block], ebx ; сохраняем указатеть на dir_rec |
mov eax, [ebx + EXT2_DIR_STRUC.inode] |
mov ebx, [ext2_data.ext2_save_inode] |
call ext2_get_inode |
mov ebp, ebx |
clc |
ret |
;======================== |
ext2_HdGetFileInfo: |
cmp byte [esi], 0 |
jz .doit |
call ext2_find_lfn |
jnc .doit2 |
;.not_found: |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.doit: |
mov ebp, [ext2_data.root_inode] |
mov ebx, .doit ;неважно что лишь бы этому адресу не '.' |
jmp @F |
.doit2: |
mov ebx, [EXT2_end_block] |
add ebx, EXT2_DIR_STRUC.name |
@@: |
xor eax, eax |
mov edi, edx |
mov ecx, 40/4 |
rep stosd ; fill zero |
cmp byte [ebx], '.' |
jnz @F |
or dword [edx], FS_FT_HIDDEN |
@@: |
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
jnz @F |
mov eax, [ebp + EXT2_INODE_STRUC.i_size] ;low size |
mov ebx, [ebp + EXT2_INODE_STRUC.i_dir_acl] ;high size |
mov dword [edx+32], eax |
mov dword [edx+36], ebx |
xor dword [edx], FS_FT_DIR |
@@: |
xor dword [edx], FS_FT_DIR |
lea edi, [edx + 8] |
mov eax, [ebx + EXT2_INODE_STRUC.i_ctime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
mov eax, [ebx + EXT2_INODE_STRUC.i_atime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
mov eax, [ebx + EXT2_INODE_STRUC.i_mtime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
xor eax, eax |
ret |
ext2_HdRewrite: |
ext2_HdWrite: |
ext2_HdSetFileEnd: |
ext2_HdSetFileInfo: |
ext2_HdDelete: |
ext2_HdCreateFolder: |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
;---------------------------------------------------------------- |
; |
; ext2_HdCreateFolder - create new folder |
; |
; esi points to filename |
; |
; ret eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
cmp byte [esi], 0 |
jz .not_found |
cmp byte [esi], '/' |
jz .not_found |
mov ebx, esi ; save source pointer |
xor edi, edi ; slah pointer |
@@: |
lodsb |
cmp al, 0 |
jz .zero |
cmp al, '/' |
jz .slash |
jmp @B |
.slash: |
lodsb |
cmp al, 0 |
jz .zero ; уберем слеш из имени |
cmp al, '/' |
jz .not_found |
mov edi, esi ; edi -> next symbol after '/' |
dec edi |
jmp @B |
.zero: |
dec esi |
test edi, edi |
jz .doit |
;слеш был |
mov eax, esi |
sub eax, edi |
mov [EXT2_name_len], eax |
mov ecx, edi |
sub ecx, ebx |
dec ecx ;выкинули '/' из имени ролителя |
mov esi, ebx |
mov edi, EXT2_parent_name |
rep movsb |
; esi - pointer to last slash |
mov edx, esi |
mov esi, EXT2_parent_name |
call ext2_find_lfn |
jnc .doit2 |
.not_found: |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.doit: |
mov ebp, [ext2_data.root_inode] |
mov edx, ebx ; имя создаваемой папки |
sub esi, ebx |
mov [EXT2_name_len], esi |
.doit2: |
;ebp -> parent_inode ebx->name_new_folder [EXT2_name_len]=length of name |
; стратегия выбора группы для нового inode: (так делает линукс) |
; 1) Ищем группу в которой меньше всего папок и в есть свободное место |
; 2) Если такая группа не нашлась, то берем группу в которой больше свободного места |
call ext2_balloc |
jmp ext2_HdDelete |
push ebx |
push ebp |
mov ecx, [ext2_data.sb] |
cmp [ecx + EXT2_SB_STRUC.free_inodes_count],0 ; есть ли место для inode |
jz .no_space |
mov eax, [ecx + EXT2_SB_STRUC.free_block_count] |
sub eax, [ecx + EXT2_SB_STRUC.r_block_count] |
cmp eax, 2 ; и как минимум на 2 блока |
jb .no_space |
mov ecx, [ext2_data.groups_count] |
mov esi, [ext2_data.global_desc_table] |
mov edi, -1 ;указатель на лучшую группу |
mov edx, 0 |
.find_group_dir: |
jecxz .end_find_group_dir |
movzx eax, [esi + EXT2_BLOCK_GROUP_DESC.free_inodes_count] |
cmp eax, edx |
jbe @F |
cmp [esi + EXT2_BLOCK_GROUP_DESC.free_blocks_count], 0 |
jz @F |
mov edi, esi |
movzx edx, [esi + EXT2_BLOCK_GROUP_DESC.free_inodes_count] |
@@: |
dec ecx |
add esi, 32 ;размер структуры |
jmp .find_group_dir |
.end_find_group_dir: |
cmp edx, 0 |
jz .no_space |
;нашли группу, получим битовую карту inode-ов (найдем locale number) |
mov eax, [edi + EXT2_BLOCK_GROUP_DESC.inode_bitmap] |
mov ebx, [ext2_data.ext2_save_block] |
call ext2_get_block |
;теперь цикл по всем битам |
mov esi, ebx |
mov ecx, [ext2_data.inodes_per_group] |
shr ecx, 5 ;делим на 32 |
mov ebp, ecx ; всего сохраним в ebp |
or eax, -1 ; ищем первый свободный inode (!= -1) |
repne scasd |
jnz .test_last_dword ;нашли или нет |
mov eax, [esi-4] |
sub ebp, ecx |
dec ebp |
shl ebp, 5 ; глобальный номер локального номера |
mov ecx, 32 |
@@: |
test eax, 1 |
jz @F |
shr eax, 1 |
loop @B |
@@: |
mov eax, 32 |
sub eax, ecx |
add ebp, eax ; locale num of inode |
mov eax, [esi-4] |
;устанавливаем в eax крайний справа нулевой бит в 1 |
mov ecx, eax |
inc ecx |
or eax, ecx ; x | (x+1) |
mov [esi-4], eax |
mov ebx, [ext2_data.ext2_save_block] |
mov eax, [edi + EXT2_BLOCK_GROUP_DESC.inode_bitmap] |
call ext2_set_block |
;считаем таблицу inode |
sub edi, [ext2_data.global_desc_table] |
shr edi, 5 |
mov eax, edi |
mul [ext2_data.inodes_per_group] |
add eax, ebp |
inc eax ; теперь в eax (ebp) номер inode-а |
mov ebp, eax |
;call ext2_get_inode_address |
mov ebx, [ext2_data.ext2_save_block] |
call hd_read |
add edx, ebx ; в edx адрес нужного inode |
;забьем 0 для начала |
mov edi, edx |
mov ecx, [ext2_data.inode_size] |
shr ecx, 2 |
xor eax, eax |
rep stosd |
mov edi, edx |
mov eax, EXT2_S_IFDIR or EXT2_777_MODE |
stosd ; i_mode |
xor eax, eax |
stosd ; i_uid |
mov eax, [ext2_data.block_size] |
stosd ; i_size |
xor eax, eax |
stosd ; i_atime |
stosd ; i_ctime |
stosd ; i_mtime |
stosd ; i_dtime |
stosd ; i_gid |
inc eax |
stosd ; i_links_count |
mov eax, [ext2_data.count_block_in_block] |
stosd ; i_blocks |
.test_last_dword: |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
.no_space: |
or ebx, -1 |
mov eax, ERROR_DISK_FULL |
ret |
;выделяет новый блок, если это можно |
;иначе возвращает eax=0 |
ext2_balloc: |
mov ecx, [ext2_data.sb] |
mov eax, [ecx + EXT2_SB_STRUC.free_block_count] |
sub eax, [ecx + EXT2_SB_STRUC.r_block_count] |
jbe .no_space |
mov ecx, [ext2_data.groups_count] |
mov edi, [ext2_data.global_desc_table] |
;mov esi, -1 ;указатель на лучшую группу |
mov edx, 0 |
.find_group: |
jecxz .end_find_group |
movzx eax, [edi + EXT2_BLOCK_GROUP_DESC.free_blocks_count] |
cmp eax, edx |
jbe @F |
mov esi, edi |
mov edx, eax |
@@: |
dec ecx |
add edi, 32 ;размер структуры |
jmp .find_group |
.end_find_group: |
cmp edx, 0 |
jz .no_space |
;нашли группу, получим битовую карту block-ов |
mov eax, [esi + EXT2_BLOCK_GROUP_DESC.block_bitmap] |
mov ebx, [ext2_data.ext2_save_block] |
call ext2_get_block |
;теперь цикл по всем битам |
mov edi, ebx |
mov ecx, [ext2_data.blocks_per_group] |
shr ecx, 5 ;делим на 32 |
mov ebp, ecx ;всего сохраним в ebp |
or eax, -1 ;ищем первый свободный inode (!= -1) |
repe scasd |
jz .test_last_dword ;нашли или нет |
mov eax, [edi-4] |
sub ebp, ecx |
dec ebp |
shl ebp, 5 ; ebp = 32*(номер div 32). Теперь найдем (номер mod 32) |
mov ecx, 32 |
@@: |
test eax, 1 |
jz @F |
shr eax, 1 |
loop @B |
@@: |
mov eax, 32 |
sub eax, ecx |
add ebp, eax ; ebp = номер блока в группе |
mov eax, [edi-4] |
mov ecx, eax |
inc ecx |
or eax, ecx ; x | (x+1) - устанавливает в 1 крайний справа нулевой бит (block used) |
mov [edi-4], eax |
mov ebx, [ext2_data.ext2_save_block] |
mov eax, [esi + EXT2_BLOCK_GROUP_DESC.inode_bitmap] |
; call ext2_set_block ; и пишем на hdd новую битовую маску |
;============== тут получаем номер блока |
mov eax, [ext2_data.blocks_per_group] |
sub esi, [ext2_data.global_desc_table] |
shr esi, 5 ;esi - номер группы |
mul esi |
add ebp, eax ;(номер_группы) * (blocks_per_group) + локальный номер в группе |
mov eax, [ext2_data.sb] |
add ebp, [eax + EXT2_SB_STRUC.first_data_block] |
;теперь поправим глобальную дескрипторную таблицу и суперблок |
mov ebx, [ext2_data.sb] |
dec [ebx + EXT2_SB_STRUC.free_block_count] |
mov eax, 2 |
add eax, [PARTITION_START] |
call hd_write |
mov eax, [ebx + EXT2_SB_STRUC.first_data_block] |
inc eax |
dec [esi + EXT2_BLOCK_GROUP_DESC.free_blocks_count];edi все еще указывает на группу в которой мы выделил блок |
call ext2_set_block |
mov eax, ebx |
ret |
.test_last_dword: |
lodsd |
mov ecx, [ext2_data.blocks_per_group] |
and ecx, not (32-1) ;обнуляем все кроме последних 5 бит |
mov edx, ecx |
mov ebx, 1 |
@@: |
jecxz .no_space |
mov edx, ebx |
or edx, eax ; тестируем очередной бит |
shl ebx, 1 |
jmp @B |
@@: |
sub edx, ecx |
dec edx ;номер в последнем блоке |
.no_space: |
xor eax, eax |
ret |
;in: eax = i_block |
; ebx = pointer to memory |
ext2_set_block: |
push eax ebx ecx |
mov ecx, [ext2_data.log_block_size] |
shl eax, cl |
add eax, [PARTITION_START] |
mov ecx, [ext2_data.count_block_in_block] |
@@: |
call hd_write |
inc eax |
add ebx, 512 |
loop @B |
pop ecx ebx eax |
ret |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/fs/part_set.inc |
---|
0,0 → 1,531 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
;************************************************************* |
;* 13.02.2010 Find all partition and check supported FS |
;* 12.07.2007 Check all 4 entry of MBR and EMBR |
;* 29.04.2006 Elimination of hangup after the |
;* expiration hd_wait_timeout - Mario79 |
;* 28.01.2006 find all Fat16/32 partition in all input point |
;* to MBR - Mario79 |
;************************************************************* |
uglobal |
align 4 |
;****************************************************** |
; Please do not change this place - variables in text |
; Mario79 |
; START place |
;****************************************************** |
PARTITION_START dd 0x3f |
PARTITION_END dd 0 |
fs_type db 0 ; 1=NTFS, 2=EXT2/3, 16=FAT16, 32=FAT32 |
align 4 |
fs_dependent_data_start: |
; FATxx data |
SECTORS_PER_FAT dd 0x1f3a |
NUMBER_OF_FATS dd 0x2 |
SECTORS_PER_CLUSTER dd 0x8 |
BYTES_PER_SECTOR dd 0x200 ; Note: if BPS <> 512 need lots of changes |
ROOT_CLUSTER dd 2 ; first rootdir cluster |
FAT_START dd 0 ; start of fat table |
ROOT_START dd 0 ; start of rootdir (only fat16) |
ROOT_SECTORS dd 0 ; count of rootdir sectors (only fat16) |
DATA_START dd 0 ; start of data area (=first cluster 2) |
LAST_CLUSTER dd 0 ; last availabe cluster |
ADR_FSINFO dd 0 ; used only by fat32 |
fatRESERVED dd 0x0FFFFFF6 |
fatBAD dd 0x0FFFFFF7 |
fatEND dd 0x0FFFFFF8 |
fatMASK dd 0x0FFFFFFF |
fatStartScan dd 2 |
fs_dependent_data_end: |
file_system_data_size = $ - PARTITION_START |
if file_system_data_size > 96 |
ERROR: sizeof(file system data) too big! |
end if |
virtual at fs_dependent_data_start |
; NTFS data |
ntfs_data: |
.sectors_per_cluster dd ? |
.mft_cluster dd ? |
.mftmirr_cluster dd ? |
.frs_size dd ? ; FRS size in bytes |
.iab_size dd ? ; IndexAllocationBuffer size in bytes |
.frs_buffer dd ? |
.iab_buffer dd ? |
.mft_retrieval dd ? |
.mft_retrieval_size dd ? |
.mft_retrieval_alloc dd ? |
.mft_retrieval_end dd ? |
.cur_index_size dd ? |
.cur_index_buf dd ? |
if $ > fs_dependent_data_end |
ERROR: increase sizeof(fs_dependent_data)! |
end if |
end virtual |
virtual at fs_dependent_data_start |
; EXT2 data |
ext2_data: |
.log_block_size dd ? |
.block_size dd ? |
.count_block_in_block dd ? |
.blocks_per_group dd ? |
.inodes_per_group dd ? |
.global_desc_table dd ? |
.root_inode dd ? ; pointer to root inode in memory |
.inode_size dd ? |
.count_pointer_in_block dd ? ; block_size / 4 |
.count_pointer_in_block_square dd ? ; (block_size / 4)**2 |
.ext2_save_block dd ? ; ¡«®ª £«®¡ «ìãî 1 ¯à®æ¥¤ãàã |
.ext2_temp_block dd ? ; ¡«®ª ¤«ï ¬¥«ª¨å ¯à®æ¥¤ãà |
.ext2_save_inode dd ? ; inode £«®¡ «ìãî ¯à®æ¥¤ãàã |
.ext2_temp_inode dd ? ; inode ¤«ï ¬¥«ª¨å ¯à®æ¥¤ãà |
.sb dd ? ; superblock |
.groups_count dd ? |
if $ > fs_dependent_data_end |
ERROR: increase sizeof(fs_dependent_data)! |
end if |
end virtual |
;*************************************************************************** |
; End place |
; Mario79 |
;*************************************************************************** |
endg |
iglobal |
partition_types: ; list of fat16/32 partitions |
db 0x04 ; DOS: fat16 <32M |
db 0x06 ; DOS: fat16 >32M |
db 0x0b ; WIN95: fat32 |
db 0x0c ; WIN95: fat32, LBA-mapped |
db 0x0e ; WIN95: fat16, LBA-mapped |
db 0x14 ; Hidden DOS: fat16 <32M |
db 0x16 ; Hidden DOS: fat16 >32M |
db 0x1b ; Hidden WIN95: fat32 |
db 0x1c ; Hidden WIN95: fat32, LBA-mapped |
db 0x1e ; Hidden WIN95: fat16, LBA-mapped |
db 0xc4 ; DRDOS/secured: fat16 <32M |
db 0xc6 ; DRDOS/secured: fat16 >32M |
db 0xcb ; DRDOS/secured: fat32 |
db 0xcc ; DRDOS/secured: fat32, LBA-mapped |
db 0xce ; DRDOS/secured: fat16, LBA-mapped |
db 0xd4 ; Old Multiuser DOS secured: fat16 <32M |
db 0xd6 ; Old Multiuser DOS secured: fat16 >32M |
db 0x07 ; NTFS |
db 0x27 ; NTFS, hidden |
db 0x83 ; Linux native file system (ext2fs) |
partition_types_end: |
extended_types: ; list of extended partitions |
db 0x05 ; DOS: extended partition |
db 0x0f ; WIN95: extended partition, LBA-mapped |
db 0xc5 ; DRDOS/secured: extended partition |
db 0xd5 ; Old Multiuser DOS secured: extended partition |
extended_types_end: |
endg |
; Partition chain used: |
; MBR <--------------------- |
; | | |
; |-> PARTITION1 | |
; |-> EXTENDED PARTITION - ;not need be second partition |
; |-> PARTITION3 |
; |-> PARTITION4 |
set_PARTITION_variables: |
set_FAT32_variables: ;deprecated |
and [problem_partition], 0 |
call reserve_hd1 |
call reserve_hd_channel |
pushad |
cmp dword [hdpos],0 |
je problem_hd |
xor ecx,ecx ; partition count |
;or edx,-1 ; flag for partition |
xor eax,eax ; address MBR |
xor ebp,ebp ; extended partition start |
new_mbr: |
test ebp,ebp ; is there extended partition? (MBR or EMBR) |
jnz extended_already_set ; yes |
xchg ebp,eax ; no. set it now |
extended_already_set: |
add eax,ebp ; mbr=mbr+0, ext_part=ext_start+relat_start |
mov ebx,buffer |
call hd_read |
cmp [hd_error],0 |
jne problem_hd |
cmp word [ebx+0x1fe],0xaa55 ; is it valid boot sector? |
jnz end_partition_chain |
push eax ; push only one time |
cmp dword [ebx+0x1be+0xc],0 ; skip over empty partition |
jnz test_primary_partition_0 |
cmp dword [ebx+0x1be+0xc+16],0 |
jnz test_primary_partition_1 |
cmp dword [ebx+0x1be+0xc+16+16],0 |
jnz test_primary_partition_2 |
cmp dword [ebx+0x1be+0xc+16+16+16],0 |
jnz test_primary_partition_3 |
pop eax |
jmp end_partition_chain |
test_primary_partition_0: |
mov al,[ebx+0x1be+4] ; get primary partition type |
call scan_partition_types |
jnz test_primary_partition_1 ; no. skip over |
inc ecx |
cmp ecx,[known_part] ; is it wanted partition? |
jnz test_primary_partition_1 ; no |
pop eax |
;mov edx, eax ; start sector |
add eax, [ebx+0x1be+8] ; add relative start |
;mov [PARTITON_START],edx |
;push edx |
mov edx, [ebx+0x1be+12] ; length |
;add edx, eax ; add length |
;dec edx ; PARTITION_END is inclusive |
;mov [PARTITION_END], edx ; note that this can be changed |
; when file system data will be available |
mov cl, [ebx+0x1be+4] ; fs_type |
;mov [fs_type], dl ; save for FS recognizer (separate FAT vs NTFS) |
;pop edx |
jmp hd_and_partition_ok |
test_primary_partition_1: |
mov al,[ebx+0x1be+4+16] ; get primary partition type |
call scan_partition_types |
jnz test_primary_partition_2 ; no. skip over |
inc ecx |
cmp ecx,[known_part] ; is it wanted partition? |
jnz test_primary_partition_2 ; no |
pop eax |
add eax, [ebx+0x1be+8+16] |
mov edx, [ebx+0x1be+12+16] |
mov cl, [ebx+0x1be+4+16] |
jmp hd_and_partition_ok |
;mov edx, eax |
;add edx, [ebx+0x1be+8+16] |
;push edx |
;add edx, [ebx+0x1be+12+16] |
;dec edx |
;mov [PARTITION_END], edx |
;mov al, [ebx+0x1be+4+16] |
;mov [fs_type], dl |
;pop edx |
test_primary_partition_2: |
mov al,[ebx+0x1be+4+16+16] ; get primary partition type |
call scan_partition_types |
jnz test_primary_partition_3 ; no. skip over |
inc ecx |
cmp ecx,[known_part] ; is it wanted partition? |
jnz test_primary_partition_3 ; no |
pop eax |
add eax, [ebx+0x1be+8+16+16] |
mov edx, [ebx+0x1be+12+16+16] |
mov cl, [ebx+0x1be+4+16+16] |
jmp hd_and_partition_ok |
;mov edx, eax |
;add edx, [ebx+0x1be+8+16+16] |
;push edx |
;add edx, [ebx+0x1be+12+16+16] |
;dec edx |
;mov [PARTITION_END], edx |
;mov al, [ebx+0x1be+4+16+16] |
;mov [fs_type], dl |
;pop edx |
test_primary_partition_3: |
mov al,[ebx+0x1be+4+16+16+16] ; get primary partition type |
call scan_partition_types |
jnz test_ext_partition_0 ; no. skip over |
inc ecx |
cmp ecx,[known_part] ; is it wanted partition? |
jnz test_ext_partition_0 ; no |
pop eax |
add eax, [ebx+0x1be+8+16+16+16] |
mov edx, [ebx+0x1be+12+16+16+16] |
mov cl, [ebx+0x1be+4+16+16+16] |
jmp hd_and_partition_ok |
;mov edx, eax |
;add edx, [ebx+0x1be+8+16+16+16] |
;push edx |
;add edx, [ebx+0x1be+12+16+16+16] |
;dec edx |
;mov [PARTITION_END], edx |
;mov al, [ebx+0x1be+4+16+16+16] |
;mov [fs_type], dl |
;pop edx |
test_ext_partition_0: |
pop eax ; ¯à®áâ® ¢ëª¨¤ë¢ ¥¬ ¨§ á⥪ |
mov al,[ebx+0x1be+4] ; get extended partition type |
call scan_extended_types |
jnz test_ext_partition_1 |
mov eax,[ebx+0x1be+8] ; add relative start |
test eax,eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
test_ext_partition_1: |
mov al,[ebx+0x1be+4+16] ; get extended partition type |
call scan_extended_types |
jnz test_ext_partition_2 |
mov eax,[ebx+0x1be+8+16] ; add relative start |
test eax,eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
test_ext_partition_2: |
mov al,[ebx+0x1be+4+16+16] ; get extended partition type |
call scan_extended_types |
jnz test_ext_partition_3 |
mov eax,[ebx+0x1be+8+16+16] ; add relative start |
test eax,eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
test_ext_partition_3: |
mov al,[ebx+0x1be+4+16+16+16] ; get extended partition type |
call scan_extended_types |
jnz end_partition_chain ; no. end chain |
mov eax,[ebx+0x1be+8+16+16+16] ; get start of extended partition |
test eax,eax ; is there extended partition? |
jnz new_mbr ; yes. read it |
end_partition_chain: |
;mov [partition_count],ecx |
;cmp edx,-1 ; found wanted partition? |
;jnz hd_and_partition_ok ; yes. install it |
;jmp problem_partition_or_fat |
problem_hd: |
or [problem_partition], 2 |
jmp return_from_part_set |
scan_partition_types: |
push ecx |
mov edi,partition_types |
mov ecx,partition_types_end-partition_types |
cld |
repne scasb ; is partition type ok? |
pop ecx |
ret |
scan_extended_types: |
push ecx |
mov edi,extended_types |
mov ecx,extended_types_end-extended_types |
cld |
repne scasb ; is it extended partition? |
pop ecx |
ret |
problem_fat_dec_count: ; bootsector is missing or another problem |
; dec [partition_count] ; remove it from partition_count |
problem_partition_or_fat: |
or [problem_partition],1 |
return_from_part_set: |
popad |
;mov [fs_type],0 |
call free_hd_channel |
mov [hd1_status],0 ; free |
ret |
hd_and_partition_ok: |
;eax = PARTITION_START edx=PARTITION_LENGTH cl=fs_type |
mov [fs_type], cl |
;mov eax,edx |
mov [PARTITION_START],eax |
add edx, eax |
dec edx |
mov [PARTITION_END], edx |
; mov edx, [PARTITION_END] |
; sub edx, eax |
; inc edx ; edx = length of partition § 祬 ®® ¬?? |
; mov [hd_setup],1 |
mov ebx,buffer |
call hd_read ; read boot sector of partition |
cmp [hd_error], 0 |
jz boot_read_ok |
cmp [fs_type], 7 |
jnz problem_fat_dec_count |
; NTFS duplicates bootsector: |
; NT4/2k/XP+ saves bootsector copy in the end of disk |
; NT 3.51 saves bootsector copy in the middle of disk |
and [hd_error], 0 |
mov eax, [PARTITION_END] |
call hd_read |
cmp [hd_error], 0 |
jnz @f |
call ntfs_test_bootsec |
jnc boot_read_ok |
@@: |
and [hd_error], 0 |
mov eax, edx |
shr eax, 1 |
add eax, [PARTITION_START] |
call hd_read |
cmp [hd_error], 0 |
jnz problem_fat_dec_count ; no chance... |
boot_read_ok: |
; if we are running on NTFS, check bootsector |
call ntfs_test_bootsec ; test ntfs |
jnc ntfs_setup |
call ext2_test_superblock ; test ext2fs |
jnc ext2_setup |
mov eax, [PARTITION_START] ;ext2 test changes [buffer] |
call hd_read |
cmp [hd_error], 0 |
jnz problem_fat_dec_count |
cmp word [ebx+0x1fe],0xaa55 ; is it valid boot sector? |
jnz problem_fat_dec_count |
movzx eax,word [ebx+0xe] ; sectors reserved |
add eax,[PARTITION_START] |
mov [FAT_START],eax ; fat_start = partition_start + reserved |
movzx eax,byte [ebx+0xd] ; sectors per cluster |
test eax,eax |
jz problem_fat_dec_count |
mov [SECTORS_PER_CLUSTER],eax |
movzx ecx,word [ebx+0xb] ; bytes per sector |
cmp ecx,0x200 |
jnz problem_fat_dec_count |
mov [BYTES_PER_SECTOR],ecx |
movzx eax,word [ebx+0x11] ; count of rootdir entries (=0 fat32) |
mov edx,32 |
mul edx |
dec ecx |
add eax,ecx ; round up if not equal count |
inc ecx ; bytes per sector |
div ecx |
mov [ROOT_SECTORS],eax ; count of rootdir sectors |
movzx eax,word [ebx+0x16] ; sectors per fat <65536 |
test eax,eax |
jnz fat16_fatsize |
mov eax,[ebx+0x24] ; sectors per fat |
fat16_fatsize: |
mov [SECTORS_PER_FAT],eax |
movzx eax,byte [ebx+0x10] ; number of fats |
test eax,eax ; if 0 it's not fat partition |
jz problem_fat_dec_count |
mov [NUMBER_OF_FATS],eax |
imul eax,[SECTORS_PER_FAT] |
add eax,[FAT_START] |
mov [ROOT_START],eax ; rootdir = fat_start + fat_size * fat_count |
add eax,[ROOT_SECTORS] ; rootdir sectors should be 0 on fat32 |
mov [DATA_START],eax ; data area = rootdir + rootdir_size |
movzx eax,word [ebx+0x13] ; total sector count <65536 |
test eax,eax |
jnz fat16_total |
mov eax,[ebx+0x20] ; total sector count |
fat16_total: |
add eax,[PARTITION_START] |
dec eax |
mov [PARTITION_END],eax |
inc eax |
sub eax,[DATA_START] ; eax = count of data sectors |
xor edx,edx |
div dword [SECTORS_PER_CLUSTER] |
inc eax |
mov [LAST_CLUSTER],eax |
dec eax ; cluster count |
mov [fatStartScan],2 |
; limits by Microsoft Hardware White Paper v1.03 |
cmp eax,4085 ; 0xff5 |
jb problem_fat_dec_count ; fat12 not supported |
cmp eax,65525 ; 0xfff5 |
jb fat16_partition |
fat32_partition: |
mov eax,[ebx+0x2c] ; rootdir cluster |
mov [ROOT_CLUSTER],eax |
movzx eax,word [ebx+0x30] ; fs info sector |
add eax,[PARTITION_START] |
mov [ADR_FSINFO],eax |
call hd_read |
mov eax,[ebx+0x1ec] |
cmp eax,-1 |
jz @f |
mov [fatStartScan],eax |
@@: |
popad |
mov [fatRESERVED],0x0FFFFFF6 |
mov [fatBAD],0x0FFFFFF7 |
mov [fatEND],0x0FFFFFF8 |
mov [fatMASK],0x0FFFFFFF |
mov [fs_type],32 ; Fat32 |
call free_hd_channel |
mov [hd1_status],0 ; free |
ret |
fat16_partition: |
xor eax,eax |
mov [ROOT_CLUSTER],eax |
popad |
mov [fatRESERVED],0x0000FFF6 |
mov [fatBAD],0x0000FFF7 |
mov [fatEND],0x0000FFF8 |
mov [fatMASK],0x0000FFFF |
mov [fs_type],16 ; Fat16 |
call free_hd_channel |
mov [hd1_status],0 ; free |
ret |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/fs/fat32.inc |
---|
0,0 → 1,2934 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; FAT32.INC ;; |
;; ;; |
;; FAT16/32 functions for KolibriOS ;; |
;; ;; |
;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;; |
;; ;; |
;; See file COPYING for details ;; |
;; 04.02.2007 LFN create folder - diamond ;; |
;; 08.10.2006 LFN delete file/folder - diamond ;; |
;; 20.08.2006 LFN set file size (truncate/extend) - diamond ;; |
;; 17.08.2006 LFN write/append to file - diamond ;; |
;; 23.06.2006 LFN start application - diamond ;; |
;; 15.06.2006 LFN get/set file/folder info - diamond ;; |
;; 27.05.2006 LFN create/rewrite file - diamond ;; |
;; 04.05.2006 LFN read folder - diamond ;; |
;; 29.04.2006 Elimination of hangup after the ;; |
;; expiration hd_wait_timeout - Mario79 ;; |
;; 23.04.2006 LFN read file - diamond ;; |
;; 28.01.2006 find all Fat16/32 partition in all input point ;; |
;; to MBR, see file part_set.inc - Mario79 ;; |
;; 15.01.2005 get file size/attr/date, file_append - ATV ;; |
;; 04.12.2004 skip volume label, file delete bug fixed - ATV ;; |
;; 29.11.2004 get_free_FAT changed, append dir bug fixed - ATV ;; |
;; 23.11.2004 don't allow overwrite dir with file - ATV ;; |
;; 18.11.2004 get_disk_info and more error codes - ATV ;; |
;; 17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV ;; |
;; 10.11.2004 removedir clear whole directory structure - ATV ;; |
;; 08.11.2004 rename - ATV ;; |
;; 30.10.2004 file_read return also dirsize in bytes - ATV ;; |
;; 20.10.2004 Makedir/Removedir - ATV ;; |
;; 14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx) ;; |
;; 06.9.2004 Fix free space by Mario79 added - MH ;; |
;; 24.5.2004 Write back buffer for File_write -VT ;; |
;; 20.5.2004 File_read function to work with syscall 58 - VT ;; |
;; 30.3.2004 Error parameters at function return - VT ;; |
;; 01.5.2002 Bugfix in device write - VT ;; |
;; 20.5.2002 Hd status check - VT ;; |
;; 29.6.2002 Improved fat32 verification - VT ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
cache_max equ 1919 ; max. is 1919*512+0x610000=0x6ffe00 |
ERROR_SUCCESS = 0 |
ERROR_DISK_BASE = 1 |
ERROR_UNSUPPORTED_FS = 2 |
ERROR_UNKNOWN_FS = 3 |
ERROR_PARTITION = 4 |
ERROR_FILE_NOT_FOUND = 5 |
ERROR_END_OF_FILE = 6 |
ERROR_MEMORY_POINTER = 7 |
ERROR_DISK_FULL = 8 |
ERROR_FAT_TABLE = 9 |
ERROR_ACCESS_DENIED = 10 |
PUSHAD_EAX equ [esp+28] |
PUSHAD_ECX equ [esp+24] |
PUSHAD_EDX equ [esp+20] |
PUSHAD_EBX equ [esp+16] |
PUSHAD_EBP equ [esp+8] |
PUSHAD_ESI equ [esp+4] |
PUSHAD_EDI equ [esp+0] |
uglobal |
align 4 |
partition_count dd 0 ; partitions found by set_FAT32_variables |
longname_sec1 dd 0 ; used by analyze_directory to save 2 previous |
longname_sec2 dd 0 ; directory sectors for delete long filename |
hd_error dd 0 ; set by wait_for_sector_buffer |
hd_setup dd 0 |
hd_wait_timeout dd 0 |
cluster_tmp dd 0 ; used by analyze_directory |
; and analyze_directory_to_write |
file_size dd 0 ; used by file_read |
cache_search_start dd 0 ; used by find_empty_slot |
endg |
iglobal |
fat_in_cache dd -1 |
endg |
uglobal |
align 4 |
fat_cache: times 512 db 0 |
Sector512: ; label for dev_hdcd.inc |
buffer: times 512 db 0 |
fsinfo_buffer: times 512 db 0 |
endg |
uglobal |
fat16_root db 0 ; flag for fat16 rootdir |
fat_change db 0 ; 1=fat has changed |
endg |
reserve_hd1: |
cli |
cmp [hd1_status],0 |
je reserve_ok1 |
sti |
call change_task |
jmp reserve_hd1 |
reserve_ok1: |
push eax |
mov eax,[CURRENT_TASK] |
shl eax,5 |
mov eax,[eax+CURRENT_TASK+TASKDATA.pid] |
mov [hd1_status],eax |
pop eax |
sti |
ret |
;******************************************** |
uglobal |
hd_in_cache db ? |
endg |
reserve_hd_channel: |
; BIOS disk accesses are protected with common mutex hd1_status |
; This must be modified when hd1_status will not be valid! |
cmp [hdpos], 0x80 |
jae .ret |
cmp [hdbase], 0x1F0 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
cli |
cmp [IDE_Channel_1],0 |
je .reserve_ok_1 |
sti |
call change_task |
jmp .IDE_Channel_1 |
.IDE_Channel_2: |
cli |
cmp [IDE_Channel_2],0 |
je .reserve_ok_2 |
sti |
call change_task |
jmp .IDE_Channel_2 |
.reserve_ok_1: |
mov [IDE_Channel_1], 1 |
push eax |
mov al, 1 |
jmp @f |
.reserve_ok_2: |
mov [IDE_Channel_2], 1 |
push eax |
mov al, 3 |
@@: |
cmp [hdid], 1 |
sbb al, -1 |
cmp al, [hd_in_cache] |
jz @f |
mov [hd_in_cache], al |
call clear_hd_cache |
@@: |
pop eax |
sti |
.ret: |
ret |
free_hd_channel: |
; see comment at reserve_hd_channel |
cmp [hdpos], 0x80 |
jae .ret |
cmp [hdbase], 0x1F0 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
mov [IDE_Channel_1],0 |
.ret: |
ret |
.IDE_Channel_2: |
mov [IDE_Channel_2],0 |
ret |
;******************************************** |
problem_partition db 0 ; used for partitions search |
include 'part_set.inc' |
set_FAT: |
;-------------------------------- |
; input : EAX = cluster |
; EDX = value to save |
; output : EDX = old value |
;-------------------------------- |
push eax ebx esi |
cmp eax,2 |
jb sfc_error |
cmp eax,[LAST_CLUSTER] |
ja sfc_error |
cmp [fs_type],16 |
je sfc_1 |
add eax,eax |
sfc_1: |
add eax,eax |
mov esi,511 |
and esi,eax ; esi = position in fat sector |
shr eax,9 ; eax = fat sector |
add eax,[FAT_START] |
mov ebx,fat_cache |
cmp eax,[fat_in_cache] ; is fat sector already in memory? |
je sfc_in_cache ; yes |
cmp [fat_change],0 ; is fat changed? |
je sfc_no_change ; no |
call write_fat_sector ; yes. write it into disk |
cmp [hd_error],0 |
jne sfc_error |
sfc_no_change: |
mov [fat_in_cache],eax ; save fat sector |
call hd_read |
cmp [hd_error],0 |
jne sfc_error |
sfc_in_cache: |
cmp [fs_type],16 |
jne sfc_test32 |
sfc_set16: |
xchg [ebx+esi],dx ; save new value and get old value |
jmp sfc_write |
sfc_test32: |
mov eax,[fatMASK] |
sfc_set32: |
and edx,eax |
xor eax,-1 ; mask for high bits |
and eax,[ebx+esi] ; get high 4 bits |
or eax,edx |
mov edx,[ebx+esi] ; get old value |
mov [ebx+esi],eax ; save new value |
sfc_write: |
mov [fat_change],1 ; fat has changed |
sfc_nonzero: |
and edx,[fatMASK] |
sfc_error: |
pop esi ebx eax |
ret |
get_FAT: |
;-------------------------------- |
; input : EAX = cluster |
; output : EAX = next cluster |
;-------------------------------- |
push ebx esi |
cmp [fs_type],16 |
je gfc_1 |
add eax,eax |
gfc_1: |
add eax,eax |
mov esi,511 |
and esi,eax ; esi = position in fat sector |
shr eax,9 ; eax = fat sector |
add eax,[FAT_START] |
mov ebx,fat_cache |
cmp eax,[fat_in_cache] ; is fat sector already in memory? |
je gfc_in_cache |
cmp [fat_change],0 ; is fat changed? |
je gfc_no_change ; no |
call write_fat_sector ; yes. write it into disk |
cmp [hd_error],0 |
jne hd_error_01 |
gfc_no_change: |
mov [fat_in_cache],eax |
call hd_read |
cmp [hd_error],0 |
jne hd_error_01 |
gfc_in_cache: |
mov eax,[ebx+esi] |
and eax,[fatMASK] |
hd_error_01: |
pop esi ebx |
ret |
get_free_FAT: |
;----------------------------------------------------------- |
; output : if CARRY=0 EAX = # first cluster found free |
; if CARRY=1 disk full |
; Note : for more speed need to use fat_cache directly |
;----------------------------------------------------------- |
push ecx |
mov ecx,[LAST_CLUSTER] ; counter for full disk |
sub ecx,2 |
mov eax,[fatStartScan] |
cmp eax,2 |
jb gff_reset |
gff_test: |
cmp eax,[LAST_CLUSTER] ; if above last cluster start at cluster 2 |
jbe gff_in_range |
gff_reset: |
mov eax,2 |
gff_in_range: |
push eax |
call get_FAT ; get cluster state |
cmp [hd_error],0 |
jne gff_not_found_1 |
test eax,eax ; is it free? |
pop eax |
je gff_found ; yes |
inc eax ; next cluster |
dec ecx ; is all checked? |
jns gff_test ; no |
gff_not_found_1: |
add esp,4 |
gff_not_found: |
pop ecx ; yes. disk is full |
stc |
ret |
gff_found: |
lea ecx,[eax+1] |
mov [fatStartScan],ecx |
pop ecx |
clc |
ret |
write_fat_sector: |
;----------------------------------------------------------- |
; write changed fat to disk |
;----------------------------------------------------------- |
push eax ebx ecx |
mov [fat_change],0 |
mov eax,[fat_in_cache] |
cmp eax,-1 |
jz write_fat_not_used |
mov ebx,fat_cache |
mov ecx,[NUMBER_OF_FATS] |
write_next_fat: |
call hd_write |
cmp [hd_error],0 |
jne write_fat_not_used |
add eax,[SECTORS_PER_FAT] |
dec ecx |
jnz write_next_fat |
write_fat_not_used: |
pop ecx ebx eax |
ret |
analyze_directory: |
;----------------------------------------------------------- |
; input : EAX = first cluster of the directory |
; EBX = pointer to filename |
; output : IF CARRY=0 EAX = sector where th file is found |
; EBX = pointer in buffer |
; [buffer .. buffer+511] |
; ECX,EDX,ESI,EDI not changed |
; IF CARRY=1 filename not found |
; Note : if cluster=0 it's changed to read rootdir |
; save 2 previous directory sectors in longname_sec |
;----------------------------------------------------------- |
push ecx edx esi edi ebx ; ebx = [esp+0] |
mov [longname_sec1],0 |
mov [longname_sec2],0 |
adr_new_cluster: |
mov [cluster_tmp],eax |
mov [fat16_root],0 |
cmp eax,[LAST_CLUSTER] |
ja adr_not_found ; too big cluster number, something is wrong |
cmp eax,2 |
jnb adr_data_cluster |
mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir |
cmp [fs_type],16 |
jne adr_data_cluster |
mov eax,[ROOT_START] |
mov edx,[ROOT_SECTORS] |
mov [fat16_root],1 ; flag for fat16 rootdir |
jmp adr_new_sector |
adr_data_cluster: |
sub eax,2 |
mov edx,[SECTORS_PER_CLUSTER] |
imul eax,edx |
add eax,[DATA_START] |
adr_new_sector: |
mov ebx,buffer |
call hd_read |
cmp [hd_error],0 |
jne adr_not_found |
mov ecx,512/32 ; count of dir entrys per sector = 16 |
adr_analyze: |
mov edi,[ebx+11] ; file attribute |
and edi,0xf |
cmp edi,0xf |
je adr_long_filename |
test edi,0x8 ; skip over volume label |
jne adr_long_filename ; Note: label can be same name as file/dir |
mov esi,[esp+0] ; filename need to be uppercase |
mov edi,ebx |
push ecx |
mov ecx,11 |
cld |
rep cmpsb ; compare 8+3 filename |
pop ecx |
je adr_found |
adr_long_filename: |
add ebx,32 ; position of next dir entry |
dec ecx |
jnz adr_analyze |
mov ecx,[longname_sec1] ; save 2 previous directory sectors |
mov [longname_sec1],eax ; for delete long filename |
mov [longname_sec2],ecx |
inc eax ; next sector |
dec edx |
jne adr_new_sector |
cmp [fat16_root],1 ; end of fat16 rootdir |
je adr_not_found |
adr_next_cluster: |
mov eax,[cluster_tmp] |
call get_FAT ; get next cluster |
cmp [hd_error],0 |
jne adr_not_found |
cmp eax,2 ; incorrect fat chain? |
jb adr_not_found ; yes |
cmp eax,[fatRESERVED] ; is it end of directory? |
jb adr_new_cluster ; no. analyse it |
adr_not_found: |
pop edi edi esi edx ecx ; first edi will remove ebx |
stc ; file not found |
ret |
adr_found: |
pop edi edi esi edx ecx ; first edi will remove ebx |
clc ; file found |
ret |
get_data_cluster: |
;----------------------------------------------------------- |
; input : EAX = cluster |
; EBX = pointer to buffer |
; EDX = # blocks to read in buffer |
; ESI = # blocks to skip over |
; output : if CARRY=0 ok EBX/EDX/ESI updated |
; if CARRY=1 cluster out of range |
; Note : if cluster=0 it's changed to read rootdir |
;----------------------------------------------------------- |
push eax ecx |
mov [fat16_root],0 |
cmp eax,[LAST_CLUSTER] |
ja gdc_error ; too big cluster number, something is wrong |
cmp eax,2 |
jnb gdc_cluster |
mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir |
cmp [fs_type],16 |
jne gdc_cluster |
mov eax,[ROOT_START] |
mov ecx,[ROOT_SECTORS] ; Note: not cluster size |
mov [fat16_root],1 ; flag for fat16 rootdir |
jmp gdc_read |
gdc_cluster: |
sub eax,2 |
mov ecx,[SECTORS_PER_CLUSTER] |
imul eax,ecx |
add eax,[DATA_START] |
gdc_read: |
test esi,esi ; first wanted block |
je gdcl1 ; yes, skip count is 0 |
dec esi |
jmp gdcl2 |
gdcl1: |
call hd_read |
cmp [hd_error],0 |
jne gdc_error |
add ebx,512 ; update pointer |
dec edx |
gdcl2: |
test edx,edx ; is all read? |
je out_of_read |
inc eax ; next sector |
dec ecx |
jnz gdc_read |
out_of_read: |
pop ecx eax |
clc |
ret |
gdc_error: |
pop ecx eax |
stc |
ret |
get_cluster_of_a_path: |
;--------------------------------------------------------- |
; input : EBX = pointer to a path string |
; (example: the path "/files/data/document" become |
; "files......data.......document...0" |
; '.' = space char |
; '0' = char(0) (ASCII=0) !!! ) |
; output : if (CARRY=1) -> ERROR in the PATH |
; if (CARRY=0) -> EAX=cluster |
;--------------------------------------------------------- |
push ebx edx |
mov eax,[ROOT_CLUSTER] |
mov edx,ebx |
search_end_of_path: |
cmp byte [edx],0 |
je found_end_of_path |
inc edx ; '/' |
mov ebx,edx |
call analyze_directory |
jc directory_not_found |
mov eax,[ebx+20-2] ; read the HIGH 16bit cluster field |
mov ax,[ebx+26] ; read the LOW 16bit cluster field |
and eax,[fatMASK] |
add edx,11 ; 8+3 (name+extension) |
jmp search_end_of_path |
found_end_of_path: |
pop edx ebx |
clc ; no errors |
ret |
directory_not_found: |
pop edx ebx |
stc ; errors occour |
ret |
bcd2bin: |
;---------------------------------- |
; input : AL=BCD number (eg. 0x11) |
; output : AH=0 |
; AL=decimal number (eg. 11) |
;---------------------------------- |
xor ah,ah |
shl ax,4 |
shr al,4 |
aad |
ret |
get_date_for_file: |
;----------------------------------------------------- |
; Get date from CMOS and pack day,month,year in AX |
; DATE bits 0..4 : day of month 0..31 |
; 5..8 : month of year 1..12 |
; 9..15 : count of years from 1980 |
;----------------------------------------------------- |
mov al,0x7 ;day |
out 0x70,al |
in al,0x71 |
call bcd2bin |
ror eax,5 |
mov al,0x8 ;month |
out 0x70,al |
in al,0x71 |
call bcd2bin |
ror eax,4 |
mov al,0x9 ;year |
out 0x70,al |
in al,0x71 |
call bcd2bin |
add ax,20 ;because CMOS return only the two last |
;digit (eg. 2000 -> 00 , 2001 -> 01) and we |
rol eax,9 ;need the difference with 1980 (eg. 2001-1980) |
ret |
get_time_for_file: |
;----------------------------------------------------- |
; Get time from CMOS and pack hour,minute,second in AX |
; TIME bits 0..4 : second (the low bit is lost) |
; 5..10 : minute 0..59 |
; 11..15 : hour 0..23 |
;----------------------------------------------------- |
mov al,0x0 ;second |
out 0x70,al |
in al,0x71 |
call bcd2bin |
ror eax,6 |
mov al,0x2 ;minute |
out 0x70,al |
in al,0x71 |
call bcd2bin |
ror eax,6 |
mov al,0x4 ;hour |
out 0x70,al |
in al,0x71 |
call bcd2bin |
rol eax,11 |
ret |
set_current_time_for_entry: |
;----------------------------------------------------- |
; Set current time/date for file entry |
; input : ebx = file entry pointer |
;----------------------------------------------------- |
push eax |
call get_time_for_file ; update files date/time |
mov [ebx+22],ax |
call get_date_for_file |
mov [ebx+24],ax |
pop eax |
ret |
add_disk_free_space: |
;----------------------------------------------------- |
; input : ecx = cluster count |
; Note : negative = remove clusters from free space |
; positive = add clusters to free space |
;----------------------------------------------------- |
test ecx,ecx ; no change |
je add_dfs_no |
cmp [fs_type],32 ; free disk space only used by fat32 |
jne add_dfs_no |
push eax ebx |
mov eax,[ADR_FSINFO] |
mov ebx,fsinfo_buffer |
call hd_read |
cmp [hd_error],0 |
jne add_not_fs |
cmp dword [ebx+0x1fc],0xaa550000 ; check sector id |
jne add_not_fs |
add [ebx+0x1e8],ecx |
push [fatStartScan] |
pop dword [ebx+0x1ec] |
call hd_write |
; cmp [hd_error],0 |
; jne add_not_fs |
add_not_fs: |
pop ebx eax |
add_dfs_no: |
ret |
file_read: |
;-------------------------------------------------------------------------- |
; INPUT : user-register register-in-this meaning symbol-in-this |
; |
; EAX EDI system call to write / |
; EBX EAX (PAR0) pointer to file-name PAR0 |
; EDX ECX (PAR1) pointer to buffer PAR1 |
; ECX EBX (PAR2) vt file blocks to read PAR2 |
; ESI EDX (PAR3) pointer to path PAR3 |
; EDI ESI vt first 512 block to read |
; EDI if 0 - read root |
; |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 6 - end of file |
; 9 - fat table corrupted |
; 10 - access denied |
; ebx = size of file/directory |
;-------------------------------------------------------------------------- |
cmp [fs_type], 16 |
jz fat_ok_for_reading |
cmp [fs_type], 32 |
jz fat_ok_for_reading |
xor ebx,ebx |
mov eax,ERROR_UNKNOWN_FS |
mov [hd1_status], ebx |
ret |
fat_ok_for_reading: |
; call reserve_hd1 |
pushad |
mov ebx,edx |
call get_cluster_of_a_path |
jc file_to_read_not_found |
test edi,edi ; read rootdir |
jne no_read_root |
xor eax,eax |
call get_dir_size ; return rootdir size |
cmp [hd_error],0 |
jne file_access_denied |
mov [file_size],eax |
mov eax,[ROOT_CLUSTER] |
jmp file_read_start |
no_read_root: |
mov ebx,PUSHAD_EAX ; file name |
call analyze_directory |
jc file_to_read_not_found |
mov eax,[ebx+28] ; file size |
test byte [ebx+11],0x10 ; is it directory? |
jz read_set_size ; no |
mov eax,[ebx+20-2] ; FAT entry |
mov ax,[ebx+26] |
and eax,[fatMASK] |
call get_dir_size |
cmp [hd_error],0 |
jne file_access_denied |
read_set_size: |
mov [file_size],eax |
mov eax,[ebx+20-2] ; FAT entry |
mov ax,[ebx+26] |
and eax,[fatMASK] |
file_read_start: |
mov ebx,PUSHAD_ECX ; pointer to buffer |
mov edx,PUSHAD_EBX ; file blocks to read |
mov esi,PUSHAD_ESI ; first 512 block to read |
file_read_new_cluster: |
call get_data_cluster |
jc file_read_eof ; end of file or cluster out of range |
test edx,edx ; is all read? |
je file_read_OK ; yes |
call get_FAT ; get next cluster |
cmp [hd_error],0 |
jne file_access_denied |
cmp eax,[fatRESERVED] ; end of file |
jnb file_read_eof |
cmp eax,2 ; incorrect fat chain |
jnb file_read_new_cluster |
popad |
mov [hd1_status],0 |
mov ebx,[file_size] |
mov eax,ERROR_FAT_TABLE |
ret |
file_read_eof: |
cmp [hd_error],0 |
jne file_access_denied |
popad |
mov [hd1_status],0 |
mov ebx,[file_size] |
mov eax,ERROR_END_OF_FILE |
ret |
file_read_OK: |
popad |
mov [hd1_status],0 |
mov ebx,[file_size] |
xor eax,eax |
ret |
file_to_read_not_found: |
cmp [hd_error],0 |
jne file_access_denied |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
file_access_denied: |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_ACCESS_DENIED |
ret |
get_dir_size: |
;----------------------------------------------------- |
; input : eax = first cluster (0=rootdir) |
; output : eax = directory size in bytes |
;----------------------------------------------------- |
push edx |
xor edx,edx ; count of directory clusters |
test eax,eax |
jnz dir_size_next |
mov eax,[ROOT_SECTORS] |
shl eax,9 ; fat16 rootdir size in bytes |
cmp [fs_type],16 |
je dir_size_ret |
mov eax,[ROOT_CLUSTER] |
dir_size_next: |
cmp eax,2 ; incorrect fat chain |
jb dir_size_end |
cmp eax,[fatRESERVED] ; end of directory |
ja dir_size_end |
call get_FAT ; get next cluster |
cmp [hd_error],0 |
jne dir_size_ret |
inc edx |
jmp dir_size_next |
dir_size_end: |
imul eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes |
imul eax,edx |
dir_size_ret: |
pop edx |
ret |
clear_cluster_chain: |
;----------------------------------------------------- |
; input : eax = first cluster |
;----------------------------------------------------- |
push eax ecx edx |
xor ecx,ecx ; cluster count |
clean_new_chain: |
cmp eax,[LAST_CLUSTER] ; end of file |
ja delete_OK |
cmp eax,2 ; unfinished fat chain or zero length file |
jb delete_OK |
cmp eax,[ROOT_CLUSTER] ; don't remove root cluster |
jz delete_OK |
xor edx,edx |
call set_FAT ; clear fat entry |
cmp [hd_error],0 |
jne access_denied_01 |
inc ecx ; update cluster count |
mov eax,edx ; old cluster |
jmp clean_new_chain |
delete_OK: |
call add_disk_free_space ; add clusters to free disk space |
access_denied_01: |
pop edx ecx eax |
ret |
get_hd_info: |
;----------------------------------------------------------- |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 10 - access denied |
; edx = cluster size in bytes |
; ebx = total clusters on disk |
; ecx = free clusters on disk |
;----------------------------------------------------------- |
cmp [fs_type], 16 |
jz info_fat_ok |
cmp [fs_type], 32 |
jz info_fat_ok |
xor edx,edx |
xor ebx,ebx |
xor ecx,ecx |
mov eax,ERROR_UNKNOWN_FS |
ret |
info_fat_ok: |
; call reserve_hd1 |
xor ecx,ecx ; count of free clusters |
mov eax,2 |
mov ebx,[LAST_CLUSTER] |
info_cluster: |
push eax |
call get_FAT ; get cluster info |
cmp [hd_error],0 |
jne info_access_denied |
test eax,eax ; is it free? |
jnz info_used ; no |
inc ecx |
info_used: |
pop eax |
inc eax |
cmp eax,ebx ; is above last cluster? |
jbe info_cluster ; no. test next cluster |
dec ebx ; cluster count |
imul edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes |
mov [hd1_status],0 |
xor eax,eax |
ret |
info_access_denied: |
add esp,4 |
xor edx,edx |
xor ebx,ebx |
xor ecx,ecx |
mov eax,ERROR_ACCESS_DENIED |
ret |
update_disk: |
;----------------------------------------------------------- |
; write changed fat and cache to disk |
;----------------------------------------------------------- |
cmp [fat_change],0 ; is fat changed? |
je upd_no_change |
call write_fat_sector |
cmp [hd_error],0 |
jne update_disk_acces_denied |
upd_no_change: |
call write_cache |
update_disk_acces_denied: |
ret |
; \begin{diamond} |
hd_find_lfn: |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0 and edi->direntry, eax=sector |
; destroys eax |
push esi edi |
push 0 |
push 0 |
push fat16_root_first |
push fat16_root_next |
mov eax, [ROOT_CLUSTER] |
cmp [fs_type], 32 |
jz .fat32 |
.loop: |
call fat_find_lfn |
jc .notfound |
cmp byte [esi], 0 |
jz .found |
.continue: |
test byte [edi+11], 10h |
jz .notfound |
and dword [esp+12], 0 |
mov eax, [edi+20-2] |
mov ax, [edi+26] ; cluster |
.fat32: |
mov [esp+8], eax |
mov dword [esp+4], fat_notroot_first |
mov dword [esp], fat_notroot_next |
jmp .loop |
.notfound: |
add esp, 16 |
pop edi esi |
stc |
ret |
.found: |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .continue |
@@: |
lea eax, [esp+8] |
cmp dword [eax], 0 |
jz .root |
call fat_get_sector |
jmp .cmn |
.root: |
mov eax, [eax+4] |
add eax, [ROOT_START] |
.cmn: |
add esp, 20 ; CF=0 |
pop esi |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdRead - LFN variant for reading hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdRead: |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
cmp [fs_type], 1 |
jz ntfs_HdRead |
cmp [fs_type], 2 |
jz ext2_HdRead |
or ebx, -1 |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
push edi |
cmp byte [esi], 0 |
jnz @f |
.noaccess: |
pop edi |
.noaccess_2: |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
@@: |
call hd_find_lfn |
jnc .found |
pop edi |
cmp [hd_error],0 |
jne .noaccess_2 |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
test byte [edi+11], 0x10 ; do not allow read directories |
jnz .noaccess |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
xor ebx, ebx |
.reteof: |
mov eax, 6 |
pop edi |
ret |
@@: |
mov ebx, [ebx] |
.l1: |
push ecx edx |
push 0 |
mov eax, [edi+28] |
sub eax, ebx |
jb .eof |
cmp eax, ecx |
jae @f |
mov ecx, eax |
mov byte [esp], 6 |
@@: |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data |
.new_cluster: |
jecxz .new_sector |
test eax, eax |
jz .eof |
cmp eax, [fatRESERVED] |
jae .eof |
mov [cluster_tmp], eax |
dec eax |
dec eax |
mov edi, [SECTORS_PER_CLUSTER] |
imul eax, edi |
add eax, [DATA_START] |
.new_sector: |
test ecx, ecx |
jz .done |
sub ebx, 512 |
jae .skip |
add ebx, 512 |
jnz .force_buf |
cmp ecx, 512 |
jb .force_buf |
; we may read directly to given buffer |
push ebx |
mov ebx, edx |
call hd_read |
pop ebx |
cmp [hd_error],0 |
jne .noaccess_1 |
add edx, 512 |
sub ecx, 512 |
jmp .skip |
.force_buf: |
; we must read sector to temporary buffer and then copy it to destination |
push eax ebx |
mov ebx, buffer |
call hd_read |
mov eax, ebx |
pop ebx |
cmp [hd_error],0 |
jne .noaccess_3 |
add eax, ebx |
push ecx |
add ecx, ebx |
cmp ecx, 512 |
jbe @f |
mov ecx, 512 |
@@: |
sub ecx, ebx |
mov ebx, edx |
call memmove |
add edx, ecx |
sub [esp], ecx |
pop ecx |
pop eax |
xor ebx, ebx |
.skip: |
inc eax |
dec edi |
jnz .new_sector |
mov eax, [cluster_tmp] |
call get_FAT |
cmp [hd_error],0 |
jne .noaccess_1 |
jmp .new_cluster |
.noaccess_3: |
pop eax |
.noaccess_1: |
pop eax |
push 11 |
.done: |
mov ebx, edx |
pop eax edx ecx edi |
sub ebx, edx |
ret |
.eof: |
mov ebx, edx |
pop eax edx ecx |
sub ebx, edx |
jmp .reteof |
;---------------------------------------------------------------- |
; |
; fs_HdReadFolder - LFN variant for reading hard disk folder |
; |
; esi points to filename |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdReadFolder: |
cmp [fs_type], 1 |
jz ntfs_HdReadFolder |
cmp [fs_type], 2 |
jz ext2_HdReadFolder |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNSUPPORTED_FS |
pop eax |
or ebx, -1 |
ret |
@@: |
mov eax, [ROOT_CLUSTER] |
push edi |
cmp byte [esi], 0 |
jz .doit |
call hd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
test byte [edi+11], 0x10 ; do not allow read files |
jnz .found_dir |
pop edi |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
.found_dir: |
mov eax, [edi+20-2] |
mov ax, [edi+26] ; eax=cluster |
.doit: |
push esi ecx |
push ebp |
sub esp, 262*2 ; reserve space for LFN |
mov ebp, esp |
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE name |
mov ebx, [ebx] |
; init header |
push eax ecx |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
pop ecx eax |
mov byte [edx], 1 ; version |
mov esi, edi ; esi points to BDFE |
.new_cluster: |
mov [cluster_tmp], eax |
test eax, eax |
jnz @f |
cmp [fs_type], 32 |
jz .notfound |
mov eax, [ROOT_START] |
push [ROOT_SECTORS] |
push ebx |
jmp .new_sector |
@@: |
dec eax |
dec eax |
imul eax, [SECTORS_PER_CLUSTER] |
push [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
push ebx |
.new_sector: |
mov ebx, buffer |
mov edi, ebx |
call hd_read |
cmp [hd_error], 0 |
jnz .notfound2 |
add ebx, 512 |
push eax |
.l1: |
call fat_get_name |
jc .l2 |
cmp byte [edi+11], 0xF |
jnz .do_bdfe |
add edi, 0x20 |
cmp edi, ebx |
jb .do_bdfe |
pop eax |
inc eax |
dec dword [esp+4] |
jnz @f |
mov eax, [cluster_tmp] |
test eax, eax |
jz .done |
call get_FAT |
cmp [hd_error], 0 |
jnz .notfound2 |
cmp eax, 2 |
jb .done |
cmp eax, [fatRESERVED] |
jae .done |
push eax |
mov eax, [SECTORS_PER_CLUSTER] |
mov [esp+8], eax |
pop eax |
mov [cluster_tmp], eax |
dec eax |
dec eax |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
@@: |
mov ebx, buffer |
mov edi, ebx |
call hd_read |
cmp [hd_error], 0 |
jnz .notfound2 |
add ebx, 512 |
push eax |
.do_bdfe: |
inc dword [edx+8] ; new file found |
dec dword [esp+4] |
jns .l2 |
dec ecx |
js .l2 |
inc dword [edx+4] ; new file block copied |
call fat_entry_to_bdfe |
.l2: |
add edi, 0x20 |
cmp edi, ebx |
jb .l1 |
pop eax |
inc eax |
dec dword [esp+4] |
jnz .new_sector |
mov eax, [cluster_tmp] |
test eax, eax |
jz .done |
call get_FAT |
cmp [hd_error], 0 |
jnz .notfound2 |
cmp eax, 2 |
jb .done |
cmp eax, [fatRESERVED] |
jae .done |
push eax |
mov eax, [SECTORS_PER_CLUSTER] |
mov [esp+8], eax |
pop eax |
pop ebx |
add esp, 4 |
jmp .new_cluster |
.notfound2: |
add esp, 8 |
.notfound: |
add esp, 262*2+4 |
pop ebp ecx esi edi |
mov eax, ERROR_FILE_NOT_FOUND |
or ebx, -1 |
ret |
.done: |
add esp, 262*2+4+8 |
pop ebp |
mov ebx, [edx+4] |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
pop ecx esi edi |
ret |
fat16_root_next: |
cmp edi, buffer+0x200-0x20 |
jae fat16_root_next_sector |
add edi, 0x20 |
ret ; CF=0 |
fat16_root_next_sector: |
; read next sector |
push [longname_sec2] |
pop [longname_sec1] |
push ecx |
mov ecx, [eax+4] |
push ecx |
add ecx, [ROOT_START] |
mov [longname_sec2], ecx |
pop ecx |
inc ecx |
mov [eax+4], ecx |
cmp ecx, [ROOT_SECTORS] |
pop ecx |
jae fat16_root_first.readerr |
fat16_root_first: |
mov eax, [eax+4] |
add eax, [ROOT_START] |
push ebx |
mov edi, buffer |
mov ebx, edi |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jnz .readerr |
ret ; CF=0 |
.readerr: |
stc |
ret |
fat16_root_begin_write: |
push edi eax |
call fat16_root_first |
pop eax edi |
ret |
fat16_root_end_write: |
pusha |
mov eax, [eax+4] |
add eax, [ROOT_START] |
mov ebx, buffer |
call hd_write |
popa |
ret |
fat16_root_next_write: |
cmp edi, buffer+0x200 |
jae @f |
ret |
@@: |
call fat16_root_end_write |
jmp fat16_root_next_sector |
fat16_root_extend_dir: |
stc |
ret |
fat_notroot_next: |
cmp edi, buffer+0x200-0x20 |
jae fat_notroot_next_sector |
add edi, 0x20 |
ret ; CF=0 |
fat_notroot_next_sector: |
push [longname_sec2] |
pop [longname_sec1] |
push eax |
call fat_get_sector |
mov [longname_sec2], eax |
pop eax |
push ecx |
mov ecx, [eax+4] |
inc ecx |
cmp ecx, [SECTORS_PER_CLUSTER] |
jae fat_notroot_next_cluster |
mov [eax+4], ecx |
jmp @f |
fat_notroot_next_cluster: |
push eax |
mov eax, [eax] |
call get_FAT |
mov ecx, eax |
pop eax |
cmp [hd_error], 0 |
jnz fat_notroot_next_err |
cmp ecx, [fatRESERVED] |
jae fat_notroot_next_err |
mov [eax], ecx |
and dword [eax+4], 0 |
@@: |
pop ecx |
fat_notroot_first: |
call fat_get_sector |
push ebx |
mov edi, buffer |
mov ebx, edi |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jnz @f |
ret ; CF=0 |
fat_notroot_next_err: |
pop ecx |
@@: |
stc |
ret |
fat_notroot_begin_write: |
push eax edi |
call fat_notroot_first |
pop edi eax |
ret |
fat_notroot_end_write: |
call fat_get_sector |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
ret |
fat_notroot_next_write: |
cmp edi, buffer+0x200 |
jae @f |
ret |
@@: |
push eax |
call fat_notroot_end_write |
pop eax |
jmp fat_notroot_next_sector |
fat_notroot_extend_dir: |
push eax |
call get_free_FAT |
jnc .found |
pop eax |
ret ; CF=1 |
.found: |
push edx |
mov edx, [fatEND] |
call set_FAT |
mov edx, eax |
mov eax, [esp+4] |
mov eax, [eax] |
push edx |
call set_FAT |
pop edx |
cmp [hd_error], 0 |
jz @f |
pop edx |
pop eax |
stc |
ret |
@@: |
push ecx |
or ecx, -1 |
call add_disk_free_space |
; zero new cluster |
mov ecx, 512/4 |
mov edi, buffer |
push edi |
xor eax, eax |
rep stosd |
pop edi |
pop ecx |
mov eax, [esp+4] |
mov [eax], edx |
and dword [eax+4], 0 |
pop edx |
mov eax, [eax] |
dec eax |
dec eax |
push ebx ecx |
mov ecx, [SECTORS_PER_CLUSTER] |
imul eax, ecx |
add eax, [DATA_START] |
mov ebx, edi |
@@: |
call hd_write |
inc eax |
loop @b |
pop ecx ebx eax |
clc |
ret |
fat_get_sector: |
push ecx |
mov ecx, [eax] |
dec ecx |
dec ecx |
imul ecx, [SECTORS_PER_CLUSTER] |
add ecx, [DATA_START] |
add ecx, [eax+4] |
mov eax, ecx |
pop ecx |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdRewrite - LFN variant for writing hard disk |
; |
; esi points to filename |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fshrad: |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
fshrfs: |
mov eax, ERROR_UNKNOWN_FS |
xor ebx, ebx |
ret |
fs_HdCreateFolder: |
mov al, 1 |
jmp fs_HdRewrite.common |
fs_HdRewrite: |
xor eax, eax |
.common: |
cmp [fs_type], 1 |
jz ntfs_HdRewrite |
cmp [fs_type], 2 |
jz ext2_HdRewrite |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jnz fshrfs |
@@: |
cmp byte [esi], 0 |
jz fshrad |
pushad |
xor edi, edi |
push esi |
test ebp, ebp |
jz @f |
mov esi, ebp |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
lea edi, [esi-1] |
jmp @b |
@@: |
pop esi |
test edi, edi |
jnz .noroot |
test ebp, ebp |
jnz .hasebp |
mov ebp, [ROOT_CLUSTER] |
cmp [fs_type], 32 |
jz .pushnotroot |
push fat16_root_extend_dir |
push fat16_root_end_write |
push fat16_root_next_write |
push fat16_root_begin_write |
xor ebp, ebp |
push ebp |
push ebp |
push fat16_root_first |
push fat16_root_next |
jmp .common1 |
.hasebp: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [ebp], 0 |
jz .ret1 |
push ebp |
xor ebp, ebp |
call hd_find_lfn |
pop esi |
jc .notfound0 |
jmp .common0 |
.noroot: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [edi+1], 0 |
jz .ret1 |
; check existence |
mov byte [edi], 0 |
push edi |
call hd_find_lfn |
pop esi |
mov byte [esi], '/' |
jnc @f |
.notfound0: |
mov eax, ERROR_FILE_NOT_FOUND |
.ret1: |
mov [esp+28], eax |
popad |
xor ebx, ebx |
ret |
@@: |
inc esi |
.common0: |
test byte [edi+11], 0x10 ; must be directory |
mov eax, ERROR_ACCESS_DENIED |
jz .ret1 |
mov ebp, [edi+20-2] |
mov bp, [edi+26] ; ebp=cluster |
mov eax, ERROR_FAT_TABLE |
cmp ebp, 2 |
jb .ret1 |
.pushnotroot: |
push fat_notroot_extend_dir |
push fat_notroot_end_write |
push fat_notroot_next_write |
push fat_notroot_begin_write |
push 0 |
push ebp |
push fat_notroot_first |
push fat_notroot_next |
.common1: |
call fat_find_lfn |
jc .notfound |
; found |
test byte [edi+11], 10h |
jz .exists_file |
; found directory; if we are creating directory, return OK, |
; if we are creating file, say "access denied" |
add esp, 32 |
popad |
test al, al |
mov eax, ERROR_ACCESS_DENIED |
jz @f |
mov al, 0 |
@@: |
xor ebx, ebx |
ret |
.exists_file: |
; found file; if we are creating directory, return "access denied", |
; if we are creating file, delete existing file and continue |
cmp byte [esp+32+28], 0 |
jz @f |
add esp, 32 |
popad |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
@@: |
; delete FAT chain |
push edi |
xor eax, eax |
mov dword [edi+28], eax ; zero size |
xor ecx, ecx |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov word [edi+20], cx |
mov word [edi+26], cx |
test eax, eax |
jz .done1 |
@@: |
cmp eax, [fatRESERVED] |
jae .done1 |
push edx |
xor edx, edx |
call set_FAT |
mov eax, edx |
pop edx |
inc ecx |
jmp @b |
.done1: |
pop edi |
call get_time_for_file |
mov [edi+22], ax |
call get_date_for_file |
mov [edi+24], ax |
mov [edi+18], ax |
or byte [edi+11], 20h ; set 'archive' attribute |
jmp .doit |
.notfound: |
; file is not found; generate short name |
call fat_name_is_legal |
jc @f |
add esp, 32 |
popad |
mov eax, ERROR_FILE_NOT_FOUND |
xor ebx, ebx |
ret |
@@: |
sub esp, 12 |
mov edi, esp |
call fat_gen_short_name |
.test_short_name_loop: |
push esi edi ecx |
mov esi, edi |
lea eax, [esp+12+12+8] |
mov [eax], ebp |
and dword [eax+4], 0 |
call dword [eax-4] |
jc .found |
.test_short_name_entry: |
cmp byte [edi+11], 0xF |
jz .test_short_name_cont |
mov ecx, 11 |
push esi edi |
repz cmpsb |
pop edi esi |
jz .short_name_found |
.test_short_name_cont: |
lea eax, [esp+12+12+8] |
call dword [eax-8] |
jnc .test_short_name_entry |
jmp .found |
.short_name_found: |
pop ecx edi esi |
call fat_next_short_name |
jnc .test_short_name_loop |
.disk_full: |
add esp, 12+32 |
popa |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.found: |
pop ecx edi esi |
; now find space in directory |
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' |
mov al, '~' |
push ecx edi |
mov ecx, 8 |
repnz scasb |
push 1 |
pop eax ; 1 entry |
jnz .notilde |
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total |
xor eax, eax |
@@: |
cmp byte [esi], 0 |
jz @f |
inc esi |
inc eax |
jmp @b |
@@: |
sub esi, eax |
add eax, 12+13 |
mov ecx, 13 |
push edx |
cdq |
div ecx |
pop edx |
.notilde: |
push -1 |
push -1 |
push -1 |
; find <eax> successive entries in directory |
xor ecx, ecx |
push eax |
lea eax, [esp+16+8+12+8] |
mov [eax], ebp |
and dword [eax+4], 0 |
call dword [eax-4] |
pop eax |
jnc .scan_dir |
.fsfrfe3: |
add esp, 12+8+12+32 |
popad |
mov eax, 11 |
xor ebx, ebx |
ret |
.scan_dir: |
cmp byte [edi], 0 |
jz .free |
cmp byte [edi], 0xE5 |
jz .free |
xor ecx, ecx |
.scan_cont: |
push eax |
lea eax, [esp+16+8+12+8] |
call dword [eax-8] |
pop eax |
jnc .scan_dir |
cmp [hd_error], 0 |
jnz .fsfrfe3 |
push eax |
lea eax, [esp+16+8+12+8] |
call dword [eax+20] ; extend directory |
pop eax |
jnc .scan_dir |
add esp, 12+8+12+32 |
popad |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.free: |
test ecx, ecx |
jnz @f |
mov [esp], edi |
mov ecx, [esp+12+8+12+8] |
mov [esp+4], ecx |
mov ecx, [esp+12+8+12+12] |
mov [esp+8], ecx |
xor ecx, ecx |
@@: |
inc ecx |
cmp ecx, eax |
jb .scan_cont |
; found! |
; calculate name checksum |
push esi ecx |
mov esi, [esp+8+12] |
mov ecx, 11 |
xor eax, eax |
@@: |
ror al, 1 |
add al, [esi] |
inc esi |
loop @b |
pop ecx esi |
pop edi |
pop dword [esp+8+12+12] |
pop dword [esp+8+12+12] |
; edi points to first entry in free chunk |
dec ecx |
jz .nolfn |
push esi |
push eax |
lea eax, [esp+8+8+12+8] |
call dword [eax+8] ; begin write |
mov al, 40h |
.writelfn: |
or al, cl |
mov esi, [esp+4] |
push ecx |
dec ecx |
imul ecx, 13 |
add esi, ecx |
stosb |
mov cl, 5 |
call fs_RamdiskRewrite.read_symbols |
mov ax, 0xF |
stosw |
mov al, [esp+4] |
stosb |
mov cl, 6 |
call fs_RamdiskRewrite.read_symbols |
xor eax, eax |
stosw |
mov cl, 2 |
call fs_RamdiskRewrite.read_symbols |
pop ecx |
lea eax, [esp+8+8+12+8] |
call dword [eax+12] ; next write |
xor eax, eax |
loop .writelfn |
pop eax |
pop esi |
; lea eax, [esp+8+12+8] |
; call dword [eax+16] ; end write |
.nolfn: |
xchg esi, [esp] |
mov ecx, 11 |
rep movsb |
mov word [edi], 20h ; attributes |
sub edi, 11 |
pop esi ecx |
add esp, 12 |
mov byte [edi+13], 0 ; tenths of a second at file creation time |
call get_time_for_file |
mov [edi+14], ax ; creation time |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+16], ax ; creation date |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
xor ecx, ecx |
mov word [edi+20], cx ; high word of cluster |
mov word [edi+26], cx ; low word of cluster - to be filled |
mov dword [edi+28], ecx ; file size - to be filled |
cmp byte [esp+32+28], cl |
jz .doit |
; create directory |
mov byte [edi+11], 10h ; attributes: folder |
mov edx, edi |
lea eax, [esp+8] |
call dword [eax+16] ; flush directory |
push ecx |
mov ecx, [SECTORS_PER_CLUSTER] |
shl ecx, 9 |
jmp .doit2 |
.doit: |
lea eax, [esp+8] |
call dword [eax+16] ; flush directory |
push ecx |
mov ecx, [esp+4+32+24] |
.doit2: |
push ecx |
push edi |
mov esi, edx |
test ecx, ecx |
jz .done |
call get_free_FAT |
jc .diskfull |
push eax |
mov [edi+26], ax |
shr eax, 16 |
mov [edi+20], ax |
lea eax, [esp+16+8] |
call dword [eax+16] ; flush directory |
pop eax |
push edx |
mov edx, [fatEND] |
call set_FAT |
pop edx |
.write_cluster: |
push eax |
dec eax |
dec eax |
mov ebp, [SECTORS_PER_CLUSTER] |
imul eax, ebp |
add eax, [DATA_START] |
; write data |
.write_sector: |
cmp byte [esp+16+32+28], 0 |
jnz .writedir |
mov ecx, 512 |
cmp dword [esp+8], ecx |
jb .writeshort |
; we can write directly from given buffer |
mov ebx, esi |
add esi, ecx |
jmp .writecommon |
.writeshort: |
mov ecx, [esp+8] |
push ecx |
mov edi, buffer |
mov ebx, edi |
rep movsb |
.writedircont: |
mov ecx, buffer+0x200 |
sub ecx, edi |
push eax |
xor eax, eax |
rep stosb |
pop eax |
pop ecx |
.writecommon: |
call hd_write |
cmp [hd_error], 0 |
jnz .writeerr |
inc eax |
sub dword [esp+8], ecx |
jz .writedone |
dec ebp |
jnz .write_sector |
; allocate new cluster |
pop eax |
mov ecx, eax |
call get_free_FAT |
jc .diskfull |
push edx |
mov edx, [fatEND] |
call set_FAT |
xchg eax, ecx |
mov edx, ecx |
call set_FAT |
pop edx |
xchg eax, ecx |
jmp .write_cluster |
.diskfull: |
mov eax, ERROR_DISK_FULL |
jmp .ret |
.writeerr: |
pop eax |
sub esi, ecx |
mov eax, 11 |
jmp .ret |
.writedone: |
pop eax |
.done: |
xor eax, eax |
.ret: |
pop edi ecx |
mov ebx, esi |
sub ebx, edx |
pop ebp |
mov [esp+32+28], eax |
lea eax, [esp+8] |
call dword [eax+8] |
mov [edi+28], ebx |
call dword [eax+16] |
mov [esp+32+16], ebx |
lea eax, [ebx+511] |
shr eax, 9 |
mov ecx, [SECTORS_PER_CLUSTER] |
lea eax, [eax+ecx-1] |
xor edx, edx |
div ecx |
mov ecx, ebp |
sub ecx, eax |
call add_disk_free_space |
add esp, 32 |
call update_disk |
popad |
ret |
.writedir: |
push 512 |
mov edi, buffer |
mov ebx, edi |
mov ecx, [SECTORS_PER_CLUSTER] |
shl ecx, 9 |
cmp ecx, [esp+12] |
jnz .writedircont |
dec dword [esp+16] |
push esi |
mov ecx, 32/4 |
rep movsd |
pop esi |
mov dword [edi-32], '. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
push esi |
mov ecx, 32/4 |
rep movsd |
pop esi |
mov dword [edi-32], '.. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov ecx, [esp+20+8] |
cmp ecx, [ROOT_CLUSTER] |
jnz @f |
xor ecx, ecx |
@@: |
mov word [edi-32+26], cx |
shr ecx, 16 |
mov [edi-32+20], cx |
jmp .writedircont |
;---------------------------------------------------------------- |
; |
; fs_HdWrite - LFN variant for writing to hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdWrite.access_denied: |
push ERROR_ACCESS_DENIED |
fs_HdWrite.ret0: |
pop eax |
xor ebx, ebx |
ret |
fs_HdWrite.ret11: |
push 11 |
jmp fs_HdWrite.ret0 |
fs_HdWrite: |
cmp [fs_type], 1 |
jz ntfs_HdWrite |
cmp [fs_type], 2 |
jz ext2_HdWrite |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNKNOWN_FS |
jmp .ret0 |
@@: |
cmp byte [esi], 0 |
jz .access_denied |
pushad |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
popad |
push 11 |
jmp .ret0 |
@@: |
popfd |
jnc .found |
popad |
push ERROR_FILE_NOT_FOUND |
jmp .ret0 |
.found: |
; FAT does not support files larger than 4GB |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
.eof: |
popad |
push ERROR_END_OF_FILE |
jmp .ret0 |
@@: |
mov ebx, [ebx] |
.l1: |
; now edi points to direntry, ebx=start byte to write, |
; ecx=number of bytes to write, edx=data pointer |
; extend file if needed |
add ecx, ebx |
jc .eof ; FAT does not support files larger than 4GB |
push eax ; save directory sector |
push 0 ; return value=0 |
call get_time_for_file |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
push dword [edi+28] ; save current file size |
cmp ecx, [edi+28] |
jbe .length_ok |
cmp ecx, ebx |
jz .length_ok |
call hd_extend_file |
jnc .length_ok |
mov [esp+4], eax |
; hd_extend_file can return three error codes: FAT table error, device error or disk full. |
; First two cases are fatal errors, in third case we may write some data |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax |
pop eax |
mov [esp+4+28], eax |
pop eax |
popad |
xor ebx, ebx |
ret |
.disk_full: |
; correct number of bytes to write |
mov ecx, [edi+28] |
cmp ecx, ebx |
ja .length_ok |
.ret: |
call update_disk |
cmp [hd_error], 0 |
jz @f |
mov byte [esp+4], 11 |
@@: |
pop eax |
pop eax |
mov [esp+4+28], eax ; eax=return value |
pop eax |
sub edx, [esp+20] |
mov [esp+16], edx ; ebx=number of written bytes |
popad |
ret |
.length_ok: |
mov esi, [edi+28] |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov edi, eax ; edi=current cluster |
xor ebp, ebp ; ebp=current sector in cluster |
; save directory |
mov eax, [esp+8] |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
cmp [hd_error], 0 |
jz @f |
.device_err: |
mov byte [esp+4], 11 |
jmp .ret |
@@: |
; now ebx=start pos, ecx=end pos, both lie inside file |
sub ecx, ebx |
jz .ret |
.write_loop: |
; skip unmodified sectors |
cmp dword [esp], 0x200 |
jb .modify |
sub ebx, 0x200 |
jae .skip |
add ebx, 0x200 |
.modify: |
; get length of data in current sector |
push ecx |
sub ebx, 0x200 |
jb .hasdata |
neg ebx |
xor ecx, ecx |
jmp @f |
.hasdata: |
neg ebx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
; get current sector number |
mov eax, edi |
dec eax |
dec eax |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
add eax, ebp |
; load sector if needed |
cmp dword [esp+4], 0 ; we don't need to read uninitialized data |
jz .noread |
cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten |
jz .noread |
cmp ecx, esi ; (same for the last sector) |
jz .noread |
push ebx |
mov ebx, buffer |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jz @f |
.device_err2: |
pop ecx |
jmp .device_err |
@@: |
.noread: |
; zero uninitialized data if file was extended (because hd_extend_file does not this) |
push eax ecx edi |
xor eax, eax |
mov ecx, 0x200 |
sub ecx, [esp+4+12] |
jbe @f |
mov edi, buffer |
add edi, [esp+4+12] |
rep stosb |
@@: |
; zero uninitialized data in the last sector |
mov ecx, 0x200 |
sub ecx, esi |
jbe @f |
mov edi, buffer |
add edi, esi |
rep stosb |
@@: |
pop edi ecx |
; copy new data |
mov eax, edx |
neg ebx |
jecxz @f |
add ebx, buffer+0x200 |
call memmove |
xor ebx, ebx |
@@: |
pop eax |
; save sector |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
cmp [hd_error], 0 |
jnz .device_err2 |
add edx, ecx |
sub [esp], ecx |
pop ecx |
jz .ret |
.skip: |
; next sector |
inc ebp |
cmp ebp, [SECTORS_PER_CLUSTER] |
jb @f |
xor ebp, ebp |
mov eax, edi |
call get_FAT |
mov edi, eax |
cmp [hd_error], 0 |
jnz .device_err |
@@: |
sub esi, 0x200 |
jae @f |
xor esi, esi |
@@: |
sub dword [esp], 0x200 |
jae @f |
and dword [esp], 0 |
@@: jmp .write_loop |
hd_extend_file.zero_size: |
xor eax, eax |
jmp hd_extend_file.start_extend |
; extends file on hd to given size (new data area is undefined) |
; in: edi->direntry, ecx=new size |
; out: CF=0 => OK, eax=0 |
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or 11) |
hd_extend_file: |
push ebp |
mov ebp, [SECTORS_PER_CLUSTER] |
imul ebp, [BYTES_PER_SECTOR] |
push ecx |
; find the last cluster of file |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov ecx, [edi+28] |
jecxz .zero_size |
.last_loop: |
sub ecx, ebp |
jbe .last_found |
call get_FAT |
cmp [hd_error], 0 |
jz @f |
.device_err: |
pop ecx |
.device_err2: |
pop ebp |
push 11 |
.ret_err: |
pop eax |
stc |
ret |
@@: |
cmp eax, 2 |
jb .fat_err |
cmp eax, [fatRESERVED] |
jb .last_loop |
.fat_err: |
pop ecx ebp |
push ERROR_FAT_TABLE |
jmp .ret_err |
.last_found: |
push eax |
call get_FAT |
cmp [hd_error], 0 |
jz @f |
pop eax |
jmp .device_err |
@@: |
cmp eax, [fatRESERVED] |
pop eax |
jb .fat_err |
; set length to full number of clusters |
sub [edi+28], ecx |
.start_extend: |
pop ecx |
; now do extend |
push edx |
mov edx, 2 ; start scan from cluster 2 |
.extend_loop: |
cmp [edi+28], ecx |
jae .extend_done |
; add new cluster |
push eax |
call get_free_FAT |
jc .disk_full |
mov edx, [fatEND] |
call set_FAT |
mov edx, eax |
pop eax |
test eax, eax |
jz .first_cluster |
push edx |
call set_FAT |
pop edx |
jmp @f |
.first_cluster: |
ror edx, 16 |
mov [edi+20], dx |
ror edx, 16 |
mov [edi+26], dx |
@@: |
push ecx |
mov ecx, -1 |
call add_disk_free_space |
pop ecx |
mov eax, edx |
cmp [hd_error], 0 |
jnz .device_err3 |
add [edi+28], ebp |
jmp .extend_loop |
.extend_done: |
mov [edi+28], ecx |
pop edx ebp |
xor eax, eax ; CF=0 |
ret |
.device_err3: |
pop edx |
jmp .device_err2 |
.disk_full: |
pop eax edx ebp |
push ERROR_DISK_FULL |
pop eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: stc |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdSetFileEnd - set end of file on hard disk |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdSetFileEnd: |
cmp [fs_type], 1 |
jz ntfs_HdSetFileEnd |
cmp [fs_type], 2 |
jz ext2_HdSetFileEnd |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNKNOWN_FS |
.ret: |
pop eax |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
.access_denied: |
push ERROR_ACCESS_DENIED |
jmp .ret |
@@: |
push edi |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
push 11 |
jmp .ret |
@@: |
popfd |
jnc @f |
pop edi |
push ERROR_FILE_NOT_FOUND |
jmp .ret |
@@: |
; must not be directory |
test byte [edi+11], 10h |
jz @f |
pop edi |
jmp .access_denied |
@@: |
; file size must not exceed 4 Gb |
cmp dword [ebx+4], 0 |
jz @f |
pop edi |
push ERROR_END_OF_FILE |
jmp .ret |
@@: |
push eax ; save directory sector |
; set file modification date/time to current |
call fat_update_datetime |
mov eax, [ebx] |
cmp eax, [edi+28] |
jb .truncate |
ja .expand |
pop eax |
mov ebx, buffer |
call hd_write |
pop edi |
xor eax, eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
.expand: |
push ebx ebp ecx |
push dword [edi+28] ; save old size |
mov ecx, eax |
call hd_extend_file |
push eax ; return code |
jnc .expand_ok |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
.pop_ret: |
call update_disk |
pop eax ecx ebp ebx ecx edi edi |
ret |
.expand_ok: |
.disk_full: |
; save directory |
mov eax, [edi+28] |
xchg eax, [esp+20] |
mov ebx, buffer |
call hd_write |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov edi, eax |
cmp [hd_error], 0 |
jz @f |
.pop_ret11: |
mov byte [esp], 11 |
jmp .pop_ret |
@@: |
; now zero new data |
xor ebp, ebp |
; edi=current cluster, ebp=sector in cluster |
; [esp+20]=new size, [esp+4]=old size, [esp]=return code |
.zero_loop: |
sub dword [esp+4], 0x200 |
jae .next_cluster |
lea eax, [edi-2] |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
add eax, ebp |
cmp dword [esp+4], -0x200 |
jz .noread |
mov ebx, buffer |
call hd_read |
cmp [hd_error], 0 |
jnz .err_next |
.noread: |
mov ecx, [esp+4] |
neg ecx |
push edi |
mov edi, buffer+0x200 |
add edi, [esp+8] |
push eax |
xor eax, eax |
mov [esp+12], eax |
rep stosb |
pop eax |
pop edi |
call hd_write |
cmp [hd_error], 0 |
jz .next_cluster |
.err_next: |
mov byte [esp], 11 |
.next_cluster: |
sub dword [esp+20], 0x200 |
jbe .pop_ret |
inc ebp |
cmp ebp, [SECTORS_PER_CLUSTER] |
jb .zero_loop |
xor ebp, ebp |
mov eax, edi |
call get_FAT |
mov edi, eax |
cmp [hd_error], 0 |
jnz .pop_ret11 |
jmp .zero_loop |
.truncate: |
mov [edi+28], eax |
push ecx |
mov ecx, [edi+20-2] |
mov cx, [edi+26] |
push eax |
test eax, eax |
jz .zero_size |
; find new last cluster |
@@: |
mov eax, [SECTORS_PER_CLUSTER] |
shl eax, 9 |
sub [esp], eax |
jbe @f |
mov eax, ecx |
call get_FAT |
mov ecx, eax |
cmp [hd_error], 0 |
jz @b |
.device_err3: |
pop eax ecx eax edi |
push 11 |
pop eax |
ret |
@@: |
; we will zero data at the end of last sector - remember it |
push ecx |
; terminate FAT chain |
push edx |
mov eax, ecx |
mov edx, [fatEND] |
call set_FAT |
mov eax, edx |
pop edx |
cmp [hd_error], 0 |
jz @f |
.device_err4: |
pop ecx |
jmp .device_err3 |
.zero_size: |
and word [edi+20], 0 |
and word [edi+26], 0 |
push 0 |
mov eax, ecx |
@@: |
; delete FAT chain |
call clear_cluster_chain |
cmp [hd_error], 0 |
jnz .device_err4 |
; save directory |
mov eax, [esp+12] |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
cmp [hd_error], 0 |
jnz .device_err4 |
; zero last sector, ignore errors |
pop ecx |
pop eax |
dec ecx |
imul ecx, [SECTORS_PER_CLUSTER] |
add ecx, [DATA_START] |
push eax |
sar eax, 9 |
add ecx, eax |
pop eax |
and eax, 0x1FF |
jz .truncate_done |
push ebx eax |
mov eax, ecx |
mov ebx, buffer |
call hd_read |
pop eax |
lea edi, [buffer+eax] |
push ecx |
mov ecx, 0x200 |
sub ecx, eax |
xor eax, eax |
rep stosb |
pop eax |
call hd_write |
pop ebx |
.truncate_done: |
pop ecx eax edi |
call update_disk |
xor eax, eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
fs_HdGetFileInfo: |
cmp [fs_type], 1 |
jz ntfs_HdGetFileInfo |
cmp [fs_type], 2 |
jz ext2_HdGetFileInfo |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 |
ret |
@@: |
push edi |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
pop edi |
mov eax, 11 |
ret |
@@: |
popfd |
jmp fs_GetFileInfo_finish |
fs_HdSetFileInfo: |
cmp [fs_type], 1 |
jz ntfs_HdSetFileInfo |
cmp [fs_type], 2 |
jz ext2_HdSetFileInfo |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 |
ret |
@@: |
push edi |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
pop edi |
mov eax, 11 |
ret |
@@: |
popfd |
jnc @f |
pop edi |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
@@: |
push eax |
call bdfe_to_fat_entry |
pop eax |
mov ebx, buffer |
call hd_write |
call update_disk |
pop edi |
xor eax, eax |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdDelete - delete file or empty folder from hard disk |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdDelete: |
cmp [fs_type], 1 |
jz ntfs_HdDelete |
cmp [fs_type], 1 |
jz ext2_HdDelete |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
push ERROR_UNKNOWN_FS |
.pop_ret: |
pop eax |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
; cannot delete root! |
.access_denied: |
push ERROR_ACCESS_DENIED |
jmp .pop_ret |
@@: |
and [longname_sec1], 0 |
and [longname_sec2], 0 |
push edi |
call hd_find_lfn |
jnc .found |
pop edi |
push ERROR_FILE_NOT_FOUND |
jmp .pop_ret |
.found: |
cmp dword [edi], '. ' |
jz .access_denied2 |
cmp dword [edi], '.. ' |
jz .access_denied2 |
test byte [edi+11], 10h |
jz .dodel |
; we can delete only empty folders! |
pushad |
mov ebp, [edi+20-2] |
mov bp, [edi+26] |
xor ecx, ecx |
lea eax, [ebp-2] |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
mov ebx, buffer |
call hd_read |
cmp [hd_error], 0 |
jnz .err1 |
add ebx, 2*0x20 |
.checkempty: |
cmp byte [ebx], 0 |
jz .empty |
cmp byte [ebx], 0xE5 |
jnz .notempty |
add ebx, 0x20 |
cmp ebx, buffer+0x200 |
jb .checkempty |
inc ecx |
cmp ecx, [SECTORS_PER_CLUSTER] |
jb @f |
mov eax, ebp |
call get_FAT |
cmp [hd_error], 0 |
jnz .err1 |
mov ebp, eax |
xor ecx, ecx |
@@: |
lea eax, [ebp-2] |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
add eax, ecx |
mov ebx, buffer |
call hd_read |
cmp [hd_error], 0 |
jz .checkempty |
.err1: |
popad |
.err2: |
pop edi |
push 11 |
pop eax |
ret |
.notempty: |
popad |
.access_denied2: |
pop edi |
push ERROR_ACCESS_DENIED |
pop eax |
ret |
.empty: |
popad |
push ebx |
mov ebx, buffer |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jnz .err2 |
.dodel: |
push eax |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
xchg eax, [esp] |
; delete folder entry |
mov byte [edi], 0xE5 |
; delete LFN (if present) |
.lfndel: |
cmp edi, buffer |
ja @f |
cmp [longname_sec2], 0 |
jz .lfndone |
push [longname_sec2] |
push [longname_sec1] |
pop [longname_sec2] |
and [longname_sec1], 0 |
push ebx |
mov ebx, buffer |
call hd_write |
mov eax, [esp+4] |
call hd_read |
pop ebx |
pop eax |
mov edi, buffer+0x200 |
@@: |
sub edi, 0x20 |
cmp byte [edi], 0xE5 |
jz .lfndone |
cmp byte [edi+11], 0xF |
jnz .lfndone |
mov byte [edi], 0xE5 |
jmp .lfndel |
.lfndone: |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
; delete FAT chain |
pop eax |
call clear_cluster_chain |
call update_disk |
pop edi |
xor eax, eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
ret |
; \end{diamond} |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/fs/fs.inc |
---|
0,0 → 1,797 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; System service for filesystem call ;; |
;; (C) 2004 Ville Turjanmaa, License: GPL ;; |
;; 29.04.2006 Elimination of hangup after the ;; |
;; expiration hd_wait_timeout (for LBA) - Mario79 ;; |
;; 15.01.2005 get file size/attr/date, ;; |
;; file_append (only for hd) - ATV ;; |
;; 23.11.2004 test if hd/partition is set - ATV ;; |
;; 18.11.2004 get_disk_info and more error codes - ATV ;; |
;; 08.11.2004 expand_pathz and rename (only for hd) - ATV ;; |
;; 20.10.2004 Makedir/Removedir (only for hd) - ATV ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
iglobal |
dir0: db 'HARDDISK ' |
db 'RAMDISK ' |
db 'FLOPPYDISK ' |
db 0 |
dir1: db 'FIRST ' |
db 'SECOND ' |
db 'THIRD ' |
db 'FOURTH ' |
db 0 |
not_select_IDE db 0 |
hd_address_table: dd 0x1f0,0x00,0x1f0,0x10 |
dd 0x170,0x00,0x170,0x10 |
endg |
file_system: |
; IN: |
; |
; eax = 0 ; read file /RamDisk/First 6 |
; eax = 8 ; lba read |
; eax = 15 ; get_disk_info |
; |
; OUT: |
; |
; eax = 0 : read ok |
; eax = 1 : no hd base and/or partition defined |
; eax = 2 : function is unsupported for this FS |
; eax = 3 : unknown FS |
; eax = 4 : partition not defined at hd |
; eax = 5 : file not found |
; eax = 6 : end of file |
; eax = 7 : memory pointer not in application area |
; eax = 8 : disk full |
; eax = 9 : fat table corrupted |
; eax = 10 : access denied |
; eax = 11 : disk error |
; |
; ebx = size |
; \begin{diamond}[18.03.2006] |
; for subfunction 16 (start application) error codes must be negative |
; because positive values are valid PIDs |
; so possible return values are: |
; eax > 0 : process created, eax=PID |
; -0x10 <= eax < 0 : -eax is filesystem error code: |
; eax = -1 = 0xFFFFFFFF : no hd base and/or partition defined |
; eax = -3 = 0xFFFFFFFD : unknown FS |
; eax = -5 = 0xFFFFFFFB : file not found |
; eax = -6 = 0xFFFFFFFA : unexpected end of file (probably not executable file) |
; eax = -9 = 0xFFFFFFF7 : fat table corrupted |
; eax = -10 = 0xFFFFFFF6 : access denied |
; -0x20 <= eax < -0x10: eax is process creation error code: |
; eax = -0x20 = 0xFFFFFFE0 : too many processes |
; eax = -0x1F = 0xFFFFFFE1 : not Menuet/Kolibri executable |
; eax = -0x1E = 0xFFFFFFE2 : no memory |
; ebx is not changed |
; \end{diamond}[18.03.2006] |
; Extract parameters |
; add eax, std_application_base_address ; abs start of info block |
cmp dword [eax+0],15 ; GET_DISK_INFO |
je fs_info |
cmp dword [CURRENT_TASK],1 ; no memory checks for kernel requests |
jz no_checks_for_kernel |
mov edx,eax |
cmp dword [eax+0],1 |
jnz .usual_check |
mov ebx,[eax+12] |
; add ebx,std_application_base_address |
mov ecx,[eax+8] |
call check_region |
test eax,eax |
jnz area_in_app_mem |
.error_output: |
mov esi,buffer_failed |
call sys_msg_board_str |
; mov eax,7 |
mov dword [esp+36],7 |
ret |
iglobal |
buffer_failed db 'K : Buffer check failed',13,10,0 |
endg |
.usual_check: |
cmp dword [eax+0],0 |
mov ecx,512 |
jnz .small_size |
mov ecx,[eax+8] |
shl ecx,9 |
.small_size: |
mov ebx,[eax+12] |
; add ebx,std_application_base_address |
call check_region |
test eax,eax |
jz .error_output |
area_in_app_mem: |
mov eax,edx |
no_checks_for_kernel: |
fs_read: |
mov ebx,[eax+20] ; program wants root directory ? |
test bl,bl |
je fs_getroot |
test bh,bh |
jne fs_noroot |
fs_getroot: |
; \begin{diamond}[18.03.2006] |
; root - only read is allowed |
; other operations return "access denied", eax=10 |
; (execute operation returns eax=-10) |
cmp dword [eax], 0 |
jz .read_root |
mov dword [esp+36], 10 |
ret |
.read_root: |
; \end{diamond}[18.03.2006] |
mov esi,dir0 |
mov edi,[eax+12] |
; add edi,std_application_base_address |
mov ecx,11 |
push ecx |
; cld ; already is |
rep movsb |
mov al,0x10 |
stosb |
add edi,32-11-1 |
pop ecx |
rep movsb |
stosb |
and dword [esp+36],0 ; ok read |
mov dword [esp+24],32*2 ; size of root |
ret |
fs_info: ;start of code - Mihasik |
push eax |
cmp [eax+21],byte 'h' |
je fs_info_h |
cmp [eax+21],byte 'H' |
je fs_info_h |
cmp [eax+21],byte 'r' |
je fs_info_r |
cmp [eax+21],byte 'R' |
je fs_info_r |
mov eax,3 ;if unknown disk |
xor ebx,ebx |
xor ecx,ecx |
xor edx,edx |
jmp fs_info1 |
fs_info_r: |
call ramdisk_free_space ;if ramdisk |
mov ecx,edi ;free space in ecx |
shr ecx,9 ;free clusters |
mov ebx,2847 ;total clusters |
mov edx,512 ;cluster size |
xor eax,eax ;always 0 |
jmp fs_info1 |
fs_info_h: ;if harddisk |
call get_hd_info |
fs_info1: |
pop edi |
mov [esp+36],eax |
mov [esp+24],ebx ; total clusters on disk |
mov [esp+32],ecx ; free clusters on disk |
mov [edi],edx ; cluster size in bytes |
ret ;end of code - Mihasik |
fs_noroot: |
push dword [eax+0] ; read/write/delete/.../makedir/rename/lba/run |
push dword [eax+4] ; 512 block number to read |
push dword [eax+8] ; bytes to write/append or 512 blocks to read |
mov ebx,[eax+12] |
; add ebx,std_application_base_address |
push ebx ; abs start of return/save area |
lea esi,[eax+20] ; abs start of dir + filename |
mov edi,[eax+16] |
; add edi,std_application_base_address ; abs start of work area |
call expand_pathz |
push edi ; dir start |
push ebx ; name of file start |
mov eax,[edi+1] |
cmp eax,'RD ' |
je fs_yesramdisk |
cmp eax,'RAMD' |
jne fs_noramdisk |
fs_yesramdisk: |
cmp byte [edi+1+11],0 |
je fs_give_dir1 |
mov eax,[edi+1+12] |
cmp eax,'1 ' |
je fs_yesramdisk_first |
cmp eax,'FIRS' |
jne fs_noramdisk |
fs_yesramdisk_first: |
cmp dword [esp+20],8 ; LBA read ramdisk |
jne fs_no_LBA_read_ramdisk |
mov eax,[esp+16] ; LBA block to read |
mov ecx,[esp+8] ; abs pointer to return area |
call LBA_read_ramdisk |
jmp file_system_return |
fs_no_LBA_read_ramdisk: |
cmp dword [esp+20],0 ; READ |
jne fs_noramdisk_read |
mov eax,[esp+4] ; fname |
add eax,2*12+1 |
mov ebx,[esp+16] ; block start |
inc ebx |
mov ecx,[esp+12] ; block count |
mov edx,[esp+8] ; return |
mov esi,[esp+0] |
sub esi,eax |
add esi,12+1 ; file name length |
call fileread |
jmp file_system_return |
fs_noramdisk_read: |
fs_noramdisk: |
;******************************************************************** |
mov eax,[edi+1] |
cmp eax,'FD ' |
je fs_yesflpdisk |
cmp eax,'FLOP' |
jne fs_noflpdisk |
fs_yesflpdisk: |
call reserve_flp |
cmp byte [edi+1+11],0 |
je fs_give_dir1 |
mov eax,[edi+1+12] |
cmp eax,'1 ' |
je fs_yesflpdisk_first |
cmp eax,'FIRS' |
je fs_yesflpdisk_first |
cmp eax,'2 ' |
je fs_yesflpdisk_second |
cmp eax,'SECO' |
jne fs_noflpdisk |
jmp fs_yesflpdisk_second |
fs_yesflpdisk_first: |
mov [flp_number],1 |
jmp fs_yesflpdisk_start |
fs_yesflpdisk_second: |
mov [flp_number],2 |
fs_yesflpdisk_start: |
cmp dword [esp+20],0 ; READ |
jne fs_noflpdisk_read |
mov eax,[esp+4] ; fname |
add eax,2*12+1 |
mov ebx,[esp+16] ; block start |
inc ebx |
mov ecx,[esp+12] ; block count |
mov edx,[esp+8] ; return |
mov esi,[esp+0] |
sub esi,eax |
add esi,12+1 ; file name length |
call floppy_fileread |
jmp file_system_return |
fs_noflpdisk_read: |
fs_noflpdisk: |
;***************************************************************** |
mov eax,[edi+1] |
cmp eax,'HD0 ' |
je fs_yesharddisk_IDE0 |
cmp eax,'HD1 ' |
je fs_yesharddisk_IDE1 |
cmp eax,'HD2 ' |
je fs_yesharddisk_IDE2 |
cmp eax,'HD3 ' |
je fs_yesharddisk_IDE3 |
jmp old_path_harddisk |
fs_yesharddisk_IDE0: |
call reserve_hd1 |
mov [hdbase],0x1f0 |
mov [hdid],0x0 |
mov [hdpos],1 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE1: |
call reserve_hd1 |
mov [hdbase],0x1f0 |
mov [hdid],0x10 |
mov [hdpos],2 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE2: |
call reserve_hd1 |
mov [hdbase],0x170 |
mov [hdid],0x0 |
mov [hdpos],3 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE3: |
call reserve_hd1 |
mov [hdbase],0x170 |
mov [hdid],0x10 |
mov [hdpos],4 |
fs_yesharddisk_partition: |
call reserve_hd_channel |
; call choice_necessity_partition |
; jmp fs_yesharddisk_all |
jmp fs_for_new_semantic |
choice_necessity_partition: |
mov eax,[edi+1+12] |
call StringToNumber |
mov [fat32part],eax |
choice_necessity_partition_1: |
mov ecx,[hdpos] |
xor eax,eax |
mov [hd_entries], eax ; entries in hd cache |
mov edx,DRIVE_DATA+2 |
cmp ecx,0x80 |
jb search_partition_array |
mov ecx,4 |
search_partition_array: |
mov bl,[edx] |
movzx ebx,bl |
add eax,ebx |
inc edx |
loop search_partition_array |
mov ecx,[hdpos] |
mov edx,BiosDiskPartitions |
sub ecx,0x80 |
jb .s |
je .f |
@@: |
mov ebx,[edx] |
add edx,4 |
add eax,ebx |
loop @b |
jmp .f |
.s: |
sub eax,ebx |
.f: |
add eax, [known_part] ; add eax,[fat32part] |
dec eax |
xor edx,edx |
imul eax,100 |
add eax,DRIVE_DATA+0xa |
mov [transfer_adress],eax |
call partition_data_transfer_1 |
ret |
old_path_harddisk: |
mov eax,[edi+1] |
cmp eax,'HD ' |
je fs_yesharddisk |
cmp eax,'HARD' |
jne fs_noharddisk |
fs_yesharddisk: |
cmp dword [esp+20],8 ; LBA read |
jne fs_no_LBA_read |
mov eax,[esp+16] ; LBA block to read |
lea ebx,[edi+1+12] ; pointer to FIRST/SECOND/THIRD/FOURTH |
mov ecx,[esp+8] ; abs pointer to return area |
call LBA_read |
jmp file_system_return |
fs_no_LBA_read: |
cmp byte [edi+1+11],0 ; directory read |
je fs_give_dir1 |
call reserve_hd1 |
fs_for_new_semantic: |
call choice_necessity_partition |
fs_yesharddisk_all: |
mov eax,1 |
mov ebx, [esp+24+24] |
cmp [hdpos],0 ; is hd base set? |
jz hd_err_return |
cmp [fat32part],0 ; is partition set? |
jnz @f |
hd_err_return: |
call free_hd_channel |
and [hd1_status], 0 |
jmp file_system_return |
@@: |
cmp dword [esp+20],0 ; READ |
jne fs_noharddisk_read |
mov eax,[esp+0] ; /fname |
lea edi,[eax+12] |
mov byte [eax],0 ; path to asciiz |
inc eax ; filename start |
mov ebx,[esp+12] ; count to read |
mov ecx,[esp+8] ; buffer |
mov edx,[esp+4] |
add edx,12*2 ; dir start |
sub edi,edx ; path length |
mov esi,[esp+16] ; blocks to read |
call file_read |
mov edi,[esp+0] |
mov byte [edi],'/' |
call free_hd_channel |
and [hd1_status], 0 |
jmp file_system_return |
fs_noharddisk_read: |
call free_hd_channel |
and [hd1_status], 0 |
fs_noharddisk: |
; \begin{diamond}[18.03.2006] |
mov eax, 5 ; file not found |
; à ìîæåò áûòü, âîçâðàùàòü äðóãîé êîä îøèáêè? |
mov ebx, [esp+24+24] ; do not change ebx in application |
; \end{diamond}[18.03.2006] |
file_system_return: |
add esp,24 |
mov [esp+36],eax |
mov [esp+24],ebx |
ret |
fs_give_dir1: |
; \begin{diamond}[18.03.2006] |
; /RD,/FD,/HD - only read is allowed |
; other operations return "access denied", eax=10 |
; (execute operation returns eax=-10) |
cmp dword [esp+20], 0 |
jz .read |
add esp, 20 |
pop ecx |
mov dword [esp+36], 10 |
ret |
.read: |
; \end{diamond}[18.03.2006] |
mov al,0x10 |
mov ebx,1 |
mov edi,[esp+8] |
mov esi,dir1 |
fs_d1_new: |
mov ecx,11 |
; cld |
rep movsb |
stosb |
add edi,32-11-1 |
dec ebx |
jne fs_d1_new |
add esp,24 |
and dword [esp+36],0 ; ok read |
mov dword [esp+24],32*1 ; dir/data size |
ret |
LBA_read_ramdisk: |
cmp [lba_read_enabled],1 |
je lbarrl1 |
xor ebx,ebx |
mov eax,2 |
ret |
lbarrl1: |
cmp eax,18*2*80 |
jb lbarrl2 |
xor ebx,ebx |
mov eax,3 |
ret |
lbarrl2: |
pushad |
call restorefatchain |
mov edi,ecx |
mov esi,eax |
shl esi,9 |
add esi,RAMDISK |
mov ecx,512/4 |
; cld |
rep movsd |
popad |
xor ebx,ebx |
xor eax,eax |
ret |
LBA_read: |
; IN: |
; |
; eax = LBA block to read |
; ebx = pointer to FIRST/SECOND/THIRD/FOURTH |
; ecx = abs pointer to return area |
cmp [lba_read_enabled],1 |
je lbarl1 |
mov eax,2 |
ret |
lbarl1: |
call reserve_hd1 |
push eax |
push ecx |
mov edi,hd_address_table |
mov esi,dir1 |
mov eax,[ebx] |
mov edx,'1 ' |
mov ecx,4 |
blar0: |
cmp eax,[esi] |
je blar2 |
cmp eax,edx |
je blar2 |
inc edx |
add edi,8 |
add esi,11 |
dec ecx |
jnz blar0 |
mov eax,1 |
mov ebx,1 |
jmp LBA_read_ret |
blar2: |
mov eax,[edi+0] |
mov ebx,[edi+4] |
mov [hdbase],eax |
mov [hdid],ebx |
call wait_for_hd_idle |
cmp [hd_error],0 |
jne hd_lba_error |
; eax = hd port |
; ebx = set for primary (0x00) or slave (0x10) |
cli |
mov edx,eax |
inc edx |
xor eax,eax |
out dx,al |
inc edx |
inc eax |
out dx,al |
inc edx |
mov eax,[esp+4] |
out dx,al |
shr eax,8 |
inc edx |
out dx,al |
shr eax,8 |
inc edx |
out dx,al |
shr eax,8 |
inc edx |
and al,1+2+4+8 |
add al,bl |
add al,128+64+32 |
out dx,al |
inc edx |
mov al,20h |
out dx,al |
sti |
call wait_for_sector_buffer |
cmp [hd_error],0 |
jne hd_lba_error |
cli |
mov edi,[esp+0] |
mov ecx,256 |
sub edx,7 |
cld |
rep insw |
sti |
xor eax,eax |
xor ebx,ebx |
LBA_read_ret: |
mov [hd_error],0 |
mov [hd1_status],0 |
add esp,2*4 |
ret |
expand_pathz: |
; IN: |
; esi = asciiz path & file |
; edi = buffer for path & file name |
; OUT: |
; edi = directory & file : / 11 + / 11 + / 11 - zero terminated |
; ebx = /file name - zero terminated |
; esi = pointer after source |
push eax |
push ecx |
push edi ;[esp+0] |
pathz_start: |
mov byte [edi],'/' |
inc edi |
mov al,32 |
mov ecx,11 |
cld |
rep stosb ; clear filename area |
sub edi,11 |
mov ebx,edi ; start of dir/file name |
pathz_new_char: |
mov al,[esi] |
inc esi |
cmp al,0 |
je pathz_end |
cmp al,'/' |
jne pathz_not_path |
cmp edi,ebx ; skip first '/' |
jz pathz_new_char |
lea edi,[ebx+11] ; start of next directory |
jmp pathz_start |
pathz_not_path: |
cmp al,'.' |
jne pathz_not_ext |
lea edi,[ebx+8] ; start of extension |
jmp pathz_new_char |
pathz_not_ext: |
cmp al,'a' |
jb pathz_not_low |
cmp al,'z' |
ja pathz_not_low |
sub al,0x20 ; char to uppercase |
pathz_not_low: |
mov [edi],al |
inc edi |
mov eax,[esp+0] ; start_of_dest_path |
add eax,512 ; keep maximum path under 512 bytes |
cmp edi,eax |
jb pathz_new_char |
pathz_end: |
cmp ebx,edi ; if path end with '/' |
jnz pathz_put_zero ; go back 1 level |
sub ebx,12 |
pathz_put_zero: |
mov byte [ebx+11],0 |
dec ebx ; include '/' char into file name |
pop edi |
pop ecx |
pop eax |
ret |
;******************************************* |
;* string to number |
;* input eax - 4 byte string |
;* output eax - number |
;******************************************* |
StringToNumber: |
; ÏÅÐÅÂÎÄ ÑÒÐÎÊÎÂÎÃÎ ×ÈÑËÀ  ×ÈÑËÎÂÎÉ ÂÈÄ |
; Âõîä: |
; EDI - àäðåñ ñòðîêè ñ ÷èñëîì. Êîíåö ÷èñëà îòìå÷åí êîäîì 0Dh |
; Âûõîä: |
; CF - èíäèêàòîð îøèáîê: |
; 0 - îøèáîê íåò; |
; 1 - îøèáêà |
; Åñëè CF=0, òî AX - ÷èñëî. |
push bx |
push cx |
push dx |
push edi |
mov [partition_string],eax |
mov edi,partition_string |
xor cx,cx |
i1: |
mov al,[edi] |
cmp al,32 ;13 |
je i_exit |
; cmp al,'0' |
; jb err |
; cmp al,'9' |
; ja err |
sub al,48 |
shl cx,1 |
jc error |
mov bx,cx |
shl cx,1 |
jc error |
shl cx,1 |
jc error |
add cx,bx |
jc error |
cbw |
add cx,ax |
jc error |
i3: |
inc edi |
jmp i1 |
i_exit: |
mov ax,cx |
clc |
i4: |
movzx eax,ax |
pop edi |
pop dx |
pop cx |
pop bx |
ret |
error: |
stc |
jmp i4 |
partition_string: dd 0 |
db 32 |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/fs/fat12.inc |
---|
0,0 → 1,2272 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; FAT12.INC ;; |
;; (C) 2005 Mario79, License: GPL ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
n_sector dd 0 ; temporary save for sector value |
flp_status dd 0 |
clust_tmp_flp dd 0 ; used by analyze_directory and analyze_directory_to_write |
path_pointer_flp dd 0 |
pointer_file_name_flp dd 0 |
save_root_flag db 0 |
save_flag db 0 |
root_read db 0 ; 0-necessary to load root, 1-not to load root |
flp_fat db 0 ; 0-necessary to load fat, 1-not to load fat |
flp_number db 0 ; 1- Floppy A, 2-Floppy B |
old_track db 0 ; old value track |
flp_label rb 15 ; Label and ID of inserted floppy disk |
reserve_flp: |
cli |
cmp [flp_status],0 |
je reserve_flp_ok |
sti |
call change_task |
jmp reserve_flp |
reserve_flp_ok: |
push eax |
mov eax,[CURRENT_TASK] |
shl eax,5 |
mov eax,[eax+CURRENT_TASK+TASKDATA.pid] |
mov [flp_status],eax |
pop eax |
sti |
ret |
floppy_fileread: |
;---------------------------------------------------------------- |
; |
; fileread - sys floppy |
; |
; eax points to filename 11 chars - for root directory |
; ebx first wanted block ; 1+ ; if 0 then set to 1 |
; ecx number of blocks to read ; 1+ ; if 0 then set to 1 |
; edx mem location to return data |
; esi length of filename 12*X |
; edi pointer to path /fd/1/...... - for all files in nested directories |
; |
; ret ebx = size or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; 10 = access denied |
;-------------------------------------------------------------- |
mov [save_flag],0 |
mov [path_pointer_flp],edi |
test esi,esi ; return ramdisk root |
jnz fr_noroot_1 |
cmp ebx,224/16 |
jbe fr_do_1 |
mov eax,5 |
xor ebx,ebx |
mov [flp_status],ebx |
ret |
fr_do_1: |
push ebx ecx edx |
call read_flp_root |
pop edx ecx ebx |
cmp [FDC_Status],0 |
jne fdc_status_error_1 |
mov edi,edx |
dec ebx |
shl ebx,9 |
mov esi,FLOPPY_BUFF |
add esi,ebx |
shl ecx,9 |
cld |
rep movsb |
xor eax,eax |
xor ebx,ebx |
; mov eax,0 ; ok read |
; mov ebx,0 |
mov [flp_status],eax |
ret |
fdc_status_error_1: |
xor eax,eax |
mov [flp_status],eax |
mov eax,10 |
or ebx,-1 |
ret |
fr_noroot_1: |
sub esp,32 |
call expand_filename |
frfloppy_1: |
test ebx,ebx |
jnz frfl5_1 |
mov ebx,1 |
frfl5_1: |
test ecx,ecx |
jnz frfl6_1 |
mov ecx,1 |
frfl6_1: |
dec ebx |
push eax |
push eax ebx ecx edx esi edi |
call read_flp_fat |
cmp [FDC_Status],0 |
jne fdc_status_error_3_1 |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],1 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
call SeekTrack |
mov dh,14 |
l.20_1: |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne fdc_status_error_3_1 |
mov dl,16 |
mov edi,FDD_BUFF |
inc [FDD_Sector] |
l.21_1: |
mov esi,eax ;Name of file we want |
mov ecx,11 |
cld |
rep cmpsb ;Found the file? |
je fifound_1 ;Yes |
add ecx,21 |
add edi, ecx ;Advance to next entry |
dec dl |
test dl,dl |
jnz l.21_1 |
dec dh |
test dh,dh |
jnz l.20_1 |
fdc_status_error_3: |
mov eax,5 ; file not found ? |
or ebx,-1 |
add esp,32+28 |
mov [flp_status],0 |
ret |
fdc_status_error_3_2: |
cmp [FDC_Status],0 |
je fdc_status_error_3 |
fdc_status_error_3_1: |
add esp,32+28 |
jmp fdc_status_error_1 |
fifound_1: |
mov eax,[path_pointer_flp] |
cmp [eax+36],byte 0 |
je fifound_2 |
add edi,0xf |
mov eax,[edi] |
and eax,65535 |
mov ebx,[path_pointer_flp] |
add ebx,36 |
call get_cluster_of_a_path_flp |
jc fdc_status_error_3_2 |
mov ebx,[ebx-11+28] ;file size |
mov [esp+20],ebx |
mov [esp+24],ebx |
jmp fifound_3 |
fifound_2: |
mov ebx,[edi-11+28] ;file size |
mov [esp+20],ebx |
mov [esp+24],ebx |
add edi,0xf |
mov eax,[edi] |
fifound_3: |
and eax,65535 |
mov [n_sector],eax ;eax=cluster |
frnew_1: |
add eax,31 ;bootsector+2*fat+filenames |
cmp [esp+16],dword 0 ; wanted cluster ? |
jne frfl7_1 |
call read_chs_sector |
cmp [FDC_Status],0 |
jne fdc_status_error_5 |
mov edi,[esp+8] |
call give_back_application_data_1 |
add [esp+8],dword 512 |
dec dword [esp+12] ; last wanted cluster ? |
cmp [esp+12],dword 0 |
je frnoread_1 |
jmp frfl8_1 |
frfl7_1: |
dec dword [esp+16] |
frfl8_1: |
mov edi,[n_sector] |
shl edi,1 ;find next cluster from FAT |
add edi,FLOPPY_FAT |
mov eax,[edi] |
and eax,4095 |
mov edi,eax |
mov [n_sector],edi |
cmp edi,4095 ;eof - cluster |
jz frnoread2_1 |
cmp [esp+24],dword 512 ;eof - size |
jb frnoread_1 |
sub [esp+24],dword 512 |
jmp frnew_1 |
read_chs_sector: |
call calculate_chs |
call ReadSectWithRetr |
ret |
frnoread2_1: |
cmp [esp+16],dword 0 ; eof without read ? |
je frnoread_1 |
mov [fdc_irq_func],fdc_null |
pop edi esi edx ecx |
add esp,4 |
pop ebx ; ebx <- eax : size of file |
add esp,36 |
mov eax,6 ; end of file |
mov [flp_status],0 |
ret |
frnoread_1: |
pop edi esi edx ecx |
add esp,4 |
pop ebx ; ebx <- eax : size of file |
add esp,36 |
xor eax,eax |
mov [flp_status],eax |
ret |
fdc_status_error_5: |
pop edi esi edx ecx |
add esp,4 |
pop ebx ; ebx <- eax : size of file |
add esp,36 |
jmp fdc_status_error_1 |
read_flp_root: |
pusha |
call check_label |
cmp [FDC_Status],0 |
jne unnecessary_root_read |
cmp [root_read],1 |
je unnecessary_root_read |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],1 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
mov edi,FLOPPY_BUFF |
call SeekTrack |
read_flp_root_1: |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_root_read |
push edi |
call give_back_application_data_1 |
pop edi |
add edi,512 |
inc [FDD_Sector] |
cmp [FDD_Sector],16 |
jne read_flp_root_1 |
mov [root_read],1 |
unnecessary_root_read: |
popa |
ret |
read_flp_fat: |
pusha |
call check_label |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat |
cmp [flp_fat],1 |
je unnecessary_flp_fat |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],0 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
mov edi,FLOPPY_BUFF |
call SeekTrack |
read_flp_fat_1: |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat |
push edi |
call give_back_application_data_1 |
pop edi |
add edi,512 |
inc [FDD_Sector] |
cmp [FDD_Sector],19 |
jne read_flp_fat_1 |
mov [FDD_Sector],1 |
mov [FDD_Head],1 |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat |
call give_back_application_data_1 |
call calculatefatchain_flp |
mov [root_read],0 |
mov [flp_fat],1 |
unnecessary_flp_fat: |
popa |
ret |
calculatefatchain_flp: |
pushad |
mov esi,FLOPPY_BUFF |
mov edi,FLOPPY_FAT |
fcnew_1: |
mov eax,dword [esi] |
mov ebx,dword [esi+4] |
mov ecx,dword [esi+8] |
mov edx,ecx |
shr edx,4 ;8 ok |
shr dx,4 ;7 ok |
xor ch,ch |
shld ecx,ebx,20 ;6 ok |
shr cx,4 ;5 ok |
shld ebx,eax,12 |
and ebx,0x0fffffff ;4 ok |
shr bx,4 ;3 ok |
shl eax,4 |
and eax,0x0fffffff ;2 ok |
shr ax,4 ;1 ok |
mov dword [edi],eax |
add edi,4 |
mov dword [edi],ebx |
add edi,4 |
mov dword [edi],ecx |
add edi,4 |
mov dword [edi],edx |
add edi,4 |
add esi,12 |
cmp edi,FLOPPY_FAT+2856*2 ;2849 clusters |
jnz fcnew_1 |
popad |
ret |
check_label: |
pushad |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],0 ; Ñòîðîíà |
mov [FDD_Sector],1 ; Ñåêòîð |
call SetUserInterrupts |
call FDDMotorON |
call RecalibrateFDD |
cmp [FDC_Status],0 |
jne fdc_status_error |
call SeekTrack |
cmp [FDC_Status],0 |
jne fdc_status_error |
call ReadSectWithRetr |
cmp [FDC_Status],0 |
jne fdc_status_error |
mov esi,flp_label |
mov edi,FDD_BUFF+39 |
mov ecx,15 |
cld |
rep cmpsb |
je same_label |
mov [root_read],0 |
mov [flp_fat],0 |
same_label: |
mov esi,FDD_BUFF+39 |
mov edi,flp_label |
mov ecx,15 |
cld |
rep movsb |
popad |
ret |
fdc_status_error: |
popad |
ret |
save_flp_root: |
pusha |
call check_label |
cmp [FDC_Status],0 |
jne unnecessary_root_save |
cmp [root_read],0 |
je unnecessary_root_save |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],1 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
mov esi,FLOPPY_BUFF |
call SeekTrack |
save_flp_root_1: |
push esi |
call take_data_from_application_1 |
pop esi |
add esi,512 |
call WriteSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_root_save |
inc [FDD_Sector] |
cmp [FDD_Sector],16 |
jne save_flp_root_1 |
unnecessary_root_save: |
mov [fdc_irq_func],fdc_null |
popa |
ret |
save_flp_fat: |
pusha |
call check_label |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat_save |
cmp [flp_fat],0 |
je unnecessary_flp_fat_save |
call restorefatchain_flp |
mov [FDD_Track],0 ; Öèëèíäð |
mov [FDD_Head],0 ; Ñòîðîíà |
mov [FDD_Sector],2 ; Ñåêòîð |
mov esi,FLOPPY_BUFF |
call SeekTrack |
save_flp_fat_1: |
push esi |
call take_data_from_application_1 |
pop esi |
add esi,512 |
call WriteSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat_save |
inc [FDD_Sector] |
cmp [FDD_Sector],19 |
jne save_flp_fat_1 |
mov [FDD_Sector],1 |
mov [FDD_Head],1 |
call take_data_from_application_1 |
call WriteSectWithRetr |
cmp [FDC_Status],0 |
jne unnecessary_flp_fat_save |
mov [root_read],0 |
unnecessary_flp_fat_save: |
mov [fdc_irq_func],fdc_null |
popa |
ret |
restorefatchain_flp: ; restore fat chain |
pushad |
mov esi,FLOPPY_FAT |
mov edi,FLOPPY_BUFF |
fcnew2_1: |
mov eax,dword [esi] |
mov ebx,dword [esi+4] |
shl ax,4 |
shl eax,4 |
shl bx,4 |
shr ebx,4 |
shrd eax,ebx,8 |
shr ebx,8 |
mov dword [edi],eax |
add edi,4 |
mov word [edi],bx |
add edi,2 |
add esi,8 |
cmp edi,FLOPPY_BUFF+0x1200 ;4274 bytes - all used FAT |
jb fcnew2_1 |
mov esi,FLOPPY_BUFF ; duplicate fat chain |
mov edi,FLOPPY_BUFF+0x1200 |
mov ecx,0x1200/4 |
cld |
rep movsd |
popad |
ret |
save_chs_sector: |
call calculate_chs |
call WriteSectWithRetr |
ret |
calculate_chs: |
mov bl,[FDD_Track] |
mov [old_track],bl |
mov ebx,18 |
xor edx,edx |
div ebx |
inc edx |
mov [FDD_Sector],dl |
xor edx,edx |
mov ebx,2 |
div ebx |
mov [FDD_Track],al |
mov [FDD_Head],0 |
test edx,edx |
jz no_head_2 |
inc [FDD_Head] |
no_head_2: |
mov dl,[old_track] |
cmp dl,[FDD_Track] |
je no_seek_track_1 |
call SeekTrack |
no_seek_track_1: |
ret |
get_cluster_of_a_path_flp: |
;--------------------------------------------------------- |
; input : EBX = pointer to a path string |
; (example: the path "/files/data/document" become |
; "files......data.......document...0" |
; '.' = space char |
; '0' = char(0) (ASCII=0) !!! ) |
; output : if (CARRY=1) -> ERROR in the PATH |
; if (CARRY=0) -> EAX=cluster |
;--------------------------------------------------------- |
push edx |
mov edx,ebx |
search_end_of_path_flp: |
cmp [save_flag],0 |
jne search_end_of_path_flp_1 |
cmp byte [edx],0 |
je found_end_of_path_flp |
jmp search_end_of_path_flp_2 |
search_end_of_path_flp_1: |
cmp byte [edx+12],0 |
je found_end_of_path_flp |
search_end_of_path_flp_2: |
inc edx ; '/' |
call analyze_directory_flp |
jc directory_not_found_flp |
mov eax,[ebx+20-2] ; read the HIGH 16bit cluster field |
mov ax,[ebx+26] ; read the LOW 16bit cluster field |
and eax,0xfff ;[fatMASK] |
add edx,11 ; 8+3 (name+extension) |
jmp search_end_of_path_flp |
found_end_of_path_flp: |
inc edx |
mov [pointer_file_name_flp],edx |
pop edx |
clc ; no errors |
ret |
directory_not_found_flp: |
pop edx |
stc ; errors occour |
ret |
analyze_directory_flp: |
;-------------------------------- |
; input : EAX = first cluster of the directory |
; EBX = pointer to filename |
; output : IF CARRY=0 EAX = sector where th file is found |
; EBX = pointer in buffer |
; [buffer .. buffer+511] |
; ECX,EDX,EDI,EDI not changed |
; IF CARRY=1 |
;-------------------------------- |
push ebx ;[esp+16] |
push ecx |
push edx |
push esi |
push edi |
adr56_flp: |
mov [clust_tmp_flp],eax |
add eax,31 |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status],0 |
jne not_found_file_analyze_flp |
mov ecx,512/32 |
mov ebx,FDD_BUFF |
adr1_analyze_flp: |
mov esi,edx ;[esp+16] |
mov edi,ebx |
cld |
push ecx |
mov ecx,11 |
rep cmpsb |
pop ecx |
je found_file_analyze_flp |
add ebx,32 |
loop adr1_analyze_flp |
mov eax,[clust_tmp_flp] |
shl eax,1 ;find next cluster from FAT |
add eax,FLOPPY_FAT |
mov eax,[eax] |
and eax,4095 |
cmp eax,0x0ff8 |
jb adr56_flp |
not_found_file_analyze_flp: |
pop edi |
pop esi |
pop edx |
pop ecx |
add esp,4 |
stc ;file not found |
ret |
found_file_analyze_flp: |
pop edi |
pop esi |
pop edx |
pop ecx |
add esp,4 |
clc ;file found |
ret |
; \begin{diamond} |
fat_find_lfn: |
; in: esi->name |
; [esp+4] = next |
; [esp+8] = first |
; [esp+C]... - possibly parameters for first and next |
; out: CF=1 - file not found |
; else CF=0, esi->next name component, edi->direntry |
pusha |
lea eax, [esp+0Ch+20h] |
call dword [eax-4] |
jc .reterr |
sub esp, 262*2 ; reserve place for LFN |
mov ebp, esp |
push 0 ; for fat_get_name: read ASCII name |
.l1: |
call fat_get_name |
jc .l2 |
call fat_compare_name |
jz .found |
.l2: |
lea eax, [esp+0Ch+20h+262*2+4] |
call dword [eax-8] |
jnc .l1 |
add esp, 262*2+4 |
.reterr: |
stc |
popa |
ret |
.found: |
add esp, 262*2+4 |
; if this is LFN entry, advance to true entry |
cmp byte [edi+11], 0xF |
jnz @f |
lea eax, [esp+0Ch+20h] |
call dword [eax-8] |
jc .reterr |
@@: |
add esp, 8 ; CF=0 |
push esi |
push edi |
popa |
ret |
uglobal |
; this is for delete support |
fd_prev_sector dd ? |
fd_prev_prev_sector dd ? |
endg |
flp_root_next: |
cmp edi, OS_BASE+0xD200-0x20 |
jae @f |
add edi, 0x20 |
ret ; CF=0 |
@@: |
; read next sector |
inc dword [eax] |
cmp dword [eax], 14 |
jae flp_root_first.readerr |
push [fd_prev_sector] |
pop [fd_prev_prev_sector] |
push eax |
mov eax, [eax] |
add eax, 19-1 |
mov [fd_prev_sector], eax |
pop eax |
flp_root_first: |
mov eax, [eax] |
pusha |
add eax, 19 |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .readerr |
mov edi, FDD_BUFF |
ret ; CF=0 |
.readerr: |
stc |
ret |
flp_rootmem_first: |
mov edi, FLOPPY_BUFF |
clc |
ret |
flp_rootmem_next: |
add edi, 0x20 |
cmp edi, FLOPPY_BUFF+14*0x200 |
cmc |
flp_rootmem_next_write: |
flp_rootmem_begin_write: |
flp_rootmem_end_write: |
ret |
flp_rootmem_extend_dir: |
stc |
ret |
flp_notroot_next: |
cmp edi, OS_BASE+0xD200-0x20 |
jae flp_notroot_next_sector |
add edi, 0x20 |
ret ; CF=0 |
flp_notroot_next_sector: |
push ecx |
mov ecx, [eax] |
push [fd_prev_sector] |
pop [fd_prev_prev_sector] |
add ecx, 31 |
mov [fd_prev_sector], ecx |
mov ecx, [(ecx-31)*2+FLOPPY_FAT] |
and ecx, 0xFFF |
cmp ecx, 2849 |
jae flp_notroot_first.err2 |
mov [eax], ecx |
pop ecx |
flp_notroot_first: |
mov eax, [eax] |
cmp eax, 2 |
jb .err |
cmp eax, 2849 |
jae .err |
pusha |
add eax, 31 |
call read_chs_sector |
popa |
mov edi, FDD_BUFF |
cmp [FDC_Status], 0 |
jnz .err |
ret ; CF=0 |
.err2: |
pop ecx |
.err: |
stc |
ret |
flp_notroot_begin_write: |
pusha |
mov eax, [eax] |
add eax, 31 |
call read_chs_sector |
popa |
ret |
flp_notroot_end_write: |
pusha |
mov eax, [eax] |
add eax, 31 |
call save_chs_sector |
popa |
ret |
flp_notroot_next_write: |
cmp edi, OS_BASE+0xD200 |
jae @f |
ret |
@@: |
call flp_notroot_end_write |
jmp flp_notroot_next_sector |
flp_notroot_extend_dir: |
; find free cluster in FAT |
pusha |
xor eax, eax |
mov edi, FLOPPY_FAT |
mov ecx, 2849 |
repnz scasw |
jnz .notfound |
mov word [edi-2], 0xFFF ; mark as last cluster |
sub edi, FLOPPY_FAT |
shr edi, 1 |
dec edi |
mov eax, [esp+28] |
mov ecx, [eax] |
mov [FLOPPY_FAT+ecx*2], di |
mov [eax], edi |
xor eax, eax |
mov edi, FDD_BUFF |
mov ecx, 128 |
rep stosd |
popa |
call flp_notroot_end_write |
mov edi, FDD_BUFF |
clc |
ret |
.notfound: |
popa |
stc |
ret |
fd_find_lfn: |
; in: esi+ebp -> name |
; out: CF=1 - file not found |
; else CF=0 and edi->direntry, eax=directory cluster (0 for root) |
push esi edi |
push 0 |
push flp_root_first |
push flp_root_next |
.loop: |
call fat_find_lfn |
jc .notfound |
cmp byte [esi], 0 |
jz .found |
.continue: |
test byte [edi+11], 10h |
jz .notfound |
movzx eax, word [edi+26] ; cluster |
mov [esp+8], eax |
mov dword [esp+4], flp_notroot_first |
mov dword [esp], flp_notroot_next |
jmp .loop |
.notfound: |
add esp, 12 |
pop edi esi |
stc |
ret |
.found: |
test ebp, ebp |
jz @f |
mov esi, ebp |
xor ebp, ebp |
jmp .continue |
@@: |
mov eax, [esp+8] |
add eax, 31 |
cmp dword [esp], flp_root_next |
jnz @f |
add eax, -31+19 |
@@: |
add esp, 16 ; CF=0 |
pop esi |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyRead - LFN variant for reading floppy |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppyRead: |
call read_flp_fat |
cmp byte [esi], 0 |
jnz @f |
or ebx, -1 |
mov eax, 10 ; access denied |
ret |
@@: |
push edi |
call fd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, 5 ; file not found |
ret |
.found: |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
xor ebx, ebx |
.reteof: |
mov eax, 6 ; EOF |
pop edi |
ret |
@@: |
mov ebx, [ebx] |
.l1: |
push ecx edx |
push 0 |
mov eax, [edi+28] |
sub eax, ebx |
jb .eof |
cmp eax, ecx |
jae @f |
mov ecx, eax |
mov byte [esp], 6 ; EOF |
@@: |
movzx edi, word [edi+26] |
.new: |
jecxz .done |
test edi, edi |
jz .eof |
cmp edi, 0xFF8 |
jae .eof |
sub ebx, 512 |
jae .skip |
lea eax, [edi+31] |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .err |
lea eax, [FDD_BUFF+ebx+512] |
neg ebx |
push ecx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
mov ebx, edx |
call memmove |
add edx, ecx |
sub [esp], ecx |
pop ecx |
xor ebx, ebx |
.skip: |
movzx edi, word [edi*2+FLOPPY_FAT] |
jmp .new |
.done: |
mov ebx, edx |
pop eax edx ecx edi |
sub ebx, edx |
ret |
.eof: |
mov ebx, edx |
pop eax edx ecx |
jmp .reteof |
.err: |
mov ebx, edx |
pop eax edx ecx edi |
sub ebx, edx |
mov al, 11 |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyReadFolder - LFN variant for reading floppy folders |
; |
; esi points to filename |
; ebx pointer to structure: 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppyReadFolder: |
call read_flp_fat |
push edi |
cmp byte [esi], 0 |
jz .root |
call fd_find_lfn |
jnc .found |
pop edi |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
test byte [edi+11], 0x10 ; do not allow read files |
jnz .found_dir |
pop edi |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
.found_dir: |
movzx eax, word [edi+26] |
add eax, 31 |
push 0 |
jmp .doit |
.root: |
mov eax, 19 |
push 14 |
.doit: |
push ecx ebp |
sub esp, 262*2 ; reserve space for LFN |
mov ebp, esp |
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names |
mov ebx, [ebx] |
; init header |
push eax ecx |
mov edi, edx |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
pop ecx eax |
mov byte [edx], 1 ; version |
mov esi, edi ; esi points to BDFE |
.main_loop: |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .error |
mov edi, FDD_BUFF |
push eax |
.l1: |
call fat_get_name |
jc .l2 |
cmp byte [edi+11], 0xF |
jnz .do_bdfe |
add edi, 0x20 |
cmp edi, OS_BASE+0xD200 |
jb .do_bdfe |
pop eax |
inc eax |
dec byte [esp+262*2+12] |
jz .done |
jns @f |
; read next sector from FAT |
mov eax, [(eax-31-1)*2+FLOPPY_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
jae .done |
add eax, 31 |
mov byte [esp+262*2+12], 0 |
@@: |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .error |
mov edi, FDD_BUFF |
push eax |
.do_bdfe: |
inc dword [edx+8] ; new file found |
dec ebx |
jns .l2 |
dec ecx |
js .l2 |
inc dword [edx+4] ; new file block copied |
call fat_entry_to_bdfe |
.l2: |
add edi, 0x20 |
cmp edi, OS_BASE+0xD200 |
jb .l1 |
pop eax |
inc eax |
dec byte [esp+262*2+12] |
jz .done |
jns @f |
; read next sector from FAT |
mov eax, [(eax-31-1)*2+FLOPPY_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
jae .done |
add eax, 31 |
mov byte [esp+262*2+12], 0 |
@@: |
jmp .main_loop |
.error: |
add esp, 262*2+4 |
pop ebp ecx edi edi |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
.done: |
add esp, 262*2+4 |
pop ebp |
mov ebx, [edx+4] |
xor eax, eax |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
@@: |
pop ecx edi edi |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyRewrite - LFN variant for writing sys floppy |
; |
; esi points to filename |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
@@: |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
fsfrfe2: |
popad |
fsfrfe: |
mov eax, 11 |
xor ebx, ebx |
ret |
fs_FloppyCreateFolder: |
mov al, 1 |
jmp fs_FloppyRewrite.common |
fs_FloppyRewrite: |
xor eax, eax |
.common: |
cmp byte [esi], 0 |
jz @b |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz fsfrfe |
pushad |
xor edi, edi |
push esi |
test ebp, ebp |
jz @f |
mov esi, ebp |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
lea edi, [esi-1] |
jmp @b |
@@: |
pop esi |
test edi, edi |
jnz .noroot |
test ebp, ebp |
jnz .hasebp |
call read_flp_root |
cmp [FDC_Status], 0 |
jnz fsfrfe2 |
push flp_rootmem_extend_dir |
push flp_rootmem_end_write |
push flp_rootmem_next_write |
push flp_rootmem_begin_write |
xor ebp, ebp |
push ebp |
push flp_rootmem_first |
push flp_rootmem_next |
jmp .common1 |
.hasebp: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [ebp], 0 |
jz .ret1 |
push ebp |
xor ebp, ebp |
call fd_find_lfn |
pop esi |
jc .notfound0 |
jmp .common0 |
.noroot: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [edi+1], 0 |
jz .ret1 |
; check existence |
mov byte [edi], 0 |
push edi |
call fd_find_lfn |
pop esi |
mov byte [esi], '/' |
jnc @f |
.notfound0: |
mov eax, ERROR_FILE_NOT_FOUND |
.ret1: |
mov [esp+28], eax |
popad |
xor ebx, ebx |
ret |
@@: |
inc esi |
.common0: |
test byte [edi+11], 0x10 ; must be directory |
mov eax, ERROR_ACCESS_DENIED |
jz .ret1 |
movzx ebp, word [edi+26] ; ebp=cluster |
mov eax, ERROR_FAT_TABLE |
cmp ebp, 2 |
jb .ret1 |
cmp ebp, 2849 |
jae .ret1 |
push flp_notroot_extend_dir |
push flp_notroot_end_write |
push flp_notroot_next_write |
push flp_notroot_begin_write |
push ebp |
push flp_notroot_first |
push flp_notroot_next |
.common1: |
call fat_find_lfn |
jc .notfound |
; found |
test byte [edi+11], 10h |
jz .exists_file |
; found directory; if we are creating directory, return OK, |
; if we are creating file, say "access denied" |
add esp, 28 |
popad |
test al, al |
mov eax, ERROR_ACCESS_DENIED |
jz @f |
mov al, 0 |
@@: |
xor ebx, ebx |
ret |
.exists_file: |
; found file; if we are creating directory, return "access denied", |
; if we are creating file, delete existing file and continue |
cmp byte [esp+28+28], 0 |
jz @f |
add esp, 28 |
popad |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
@@: |
; delete FAT chain |
push edi |
xor eax, eax |
mov dword [edi+28], eax ; zero size |
xchg ax, word [edi+26] ; start cluster |
test eax, eax |
jz .done1 |
@@: |
cmp eax, 0xFF8 |
jae .done1 |
lea edi, [FLOPPY_FAT + eax*2] ; position in FAT |
xor eax, eax |
xchg ax, [edi] |
jmp @b |
.done1: |
pop edi |
call get_time_for_file |
mov [edi+22], ax |
call get_date_for_file |
mov [edi+24], ax |
mov [edi+18], ax |
or byte [edi+11], 20h ; set 'archive' attribute |
jmp .doit |
.notfound: |
; file is not found; generate short name |
call fat_name_is_legal |
jc @f |
add esp, 28 |
popad |
mov eax, ERROR_FILE_NOT_FOUND |
xor ebx, ebx |
ret |
@@: |
sub esp, 12 |
mov edi, esp |
call fat_gen_short_name |
.test_short_name_loop: |
push esi edi ecx |
mov esi, edi |
lea eax, [esp+12+12+8] |
mov [eax], ebp |
call dword [eax-4] |
jc .found |
.test_short_name_entry: |
cmp byte [edi+11], 0xF |
jz .test_short_name_cont |
mov ecx, 11 |
push esi edi |
repz cmpsb |
pop edi esi |
jz .short_name_found |
.test_short_name_cont: |
lea eax, [esp+12+12+8] |
call dword [eax-8] |
jnc .test_short_name_entry |
jmp .found |
.short_name_found: |
pop ecx edi esi |
call fat_next_short_name |
jnc .test_short_name_loop |
.disk_full: |
add esp, 12+28 |
popa |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.found: |
pop ecx edi esi |
; now find space in directory |
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' |
mov al, '~' |
push ecx edi |
mov ecx, 8 |
repnz scasb |
push 1 |
pop eax ; 1 entry |
jnz .notilde |
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total |
xor eax, eax |
@@: |
cmp byte [esi], 0 |
jz @f |
inc esi |
inc eax |
jmp @b |
@@: |
sub esi, eax |
add eax, 12+13 |
mov ecx, 13 |
push edx |
cdq |
div ecx |
pop edx |
.notilde: |
push -1 |
push -1 |
; find <eax> successive entries in directory |
xor ecx, ecx |
push eax |
lea eax, [esp+12+8+12+8] |
mov [eax], ebp |
call dword [eax-4] |
pop eax |
jnc .scan_dir |
.fsfrfe3: |
add esp, 8+8+12+28 |
popad |
mov eax, 11 |
xor ebx, ebx |
ret |
.scan_dir: |
cmp byte [edi], 0 |
jz .free |
cmp byte [edi], 0xE5 |
jz .free |
xor ecx, ecx |
.scan_cont: |
push eax |
lea eax, [esp+12+8+12+8] |
call dword [eax-8] |
pop eax |
jnc .scan_dir |
cmp [FDC_Status], 0 |
jnz .fsfrfe3 |
push eax |
lea eax, [esp+12+8+12+8] |
call dword [eax+16] ; extend directory |
pop eax |
jnc .scan_dir |
add esp, 8+8+12+28 |
popad |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
.free: |
test ecx, ecx |
jnz @f |
mov [esp], edi |
mov ecx, [esp+8+8+12+8] |
mov [esp+4], ecx |
xor ecx, ecx |
@@: |
inc ecx |
cmp ecx, eax |
jb .scan_cont |
; found! |
; calculate name checksum |
push esi ecx |
mov esi, [esp+8+8] |
mov ecx, 11 |
xor eax, eax |
@@: |
ror al, 1 |
add al, [esi] |
inc esi |
loop @b |
pop ecx esi |
pop edi |
pop dword [esp+8+12+8] |
; edi points to first entry in free chunk |
dec ecx |
jz .nolfn |
push esi |
push eax |
lea eax, [esp+8+8+12+8] |
call dword [eax+4] ; begin write |
mov al, 40h |
.writelfn: |
or al, cl |
mov esi, [esp+4] |
push ecx |
dec ecx |
imul ecx, 13 |
add esi, ecx |
stosb |
mov cl, 5 |
call fs_RamdiskRewrite.read_symbols |
mov ax, 0xF |
stosw |
mov al, [esp+4] |
stosb |
mov cl, 6 |
call fs_RamdiskRewrite.read_symbols |
xor eax, eax |
stosw |
mov cl, 2 |
call fs_RamdiskRewrite.read_symbols |
pop ecx |
lea eax, [esp+8+8+12+8] |
call dword [eax+8] ; next write |
xor eax, eax |
loop .writelfn |
pop eax |
pop esi |
; lea eax, [esp+8+12+8] |
; call dword [eax+12] ; end write |
.nolfn: |
xchg esi, [esp] |
mov ecx, 11 |
rep movsb |
mov word [edi], 20h ; attributes |
sub edi, 11 |
pop esi ecx |
add esp, 12 |
mov byte [edi+13], 0 ; tenths of a second at file creation time |
call get_time_for_file |
mov [edi+14], ax ; creation time |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+16], ax ; creation date |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
and word [edi+20], 0 ; high word of cluster |
and word [edi+26], 0 ; low word of cluster - to be filled |
and dword [edi+28], 0 ; file size - to be filled |
cmp byte [esp+28+28], 0 |
jz .doit |
; create directory |
mov byte [edi+11], 10h ; attributes: folder |
mov ecx, 32*2 |
mov edx, edi |
.doit: |
lea eax, [esp+8] |
call dword [eax+12] ; flush directory |
push ecx |
push edi |
push 0 |
mov esi, edx |
test ecx, ecx |
jz .done |
mov ecx, 2849 |
mov edi, FLOPPY_FAT |
push 0 ; first cluster |
.write_loop: |
; allocate new cluster |
xor eax, eax |
repnz scasw |
mov al, ERROR_DISK_FULL |
jnz .ret |
dec edi |
dec edi |
mov eax, edi |
sub eax, FLOPPY_FAT |
shr eax, 1 ; eax = cluster |
mov word [edi], 0xFFF ; mark as last cluster |
xchg edi, [esp+4] |
cmp dword [esp], 0 |
jz .first |
stosw |
jmp @f |
.first: |
mov [esp], eax |
@@: |
mov edi, [esp+4] |
inc ecx |
; write data |
push ecx edi |
mov ecx, 512 |
cmp dword [esp+20], ecx |
jae @f |
mov ecx, [esp+20] |
@@: |
mov edi, FDD_BUFF |
cmp byte [esp+24+28+28], 0 |
jnz .writedir |
push ecx |
rep movsb |
pop ecx |
.writedircont: |
push ecx |
sub ecx, 512 |
neg ecx |
push eax |
xor eax, eax |
rep stosb |
pop eax |
add eax, 31 |
pusha |
call save_chs_sector |
popa |
pop ecx |
cmp [FDC_Status], 0 |
jnz .diskerr |
sub [esp+20], ecx |
pop edi ecx |
jnz .write_loop |
.done: |
xor eax, eax |
.ret: |
pop ebx edi edi ecx |
mov [esp+28+28], eax |
lea eax, [esp+8] |
call dword [eax+4] |
mov [edi+26], bx |
mov ebx, esi |
sub ebx, edx |
mov [edi+28], ebx |
call dword [eax+12] |
mov [esp+28+16], ebx |
test ebp, ebp |
jnz @f |
call save_flp_root |
@@: |
add esp, 28 |
cmp [FDC_Status], 0 |
jnz .err3 |
call save_flp_fat |
cmp [FDC_Status], 0 |
jnz .err3 |
popa |
ret |
.err3: |
popa |
mov al, 11 |
xor ebx, ebx |
ret |
.diskerr: |
sub esi, ecx |
mov eax, 11 |
pop edi ecx |
jmp .ret |
.writedir: |
push ecx |
mov ecx, 32/4 |
push ecx esi |
rep movsd |
pop esi ecx |
mov dword [edi-32], '. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov word [edi-32+26], ax |
push esi |
rep movsd |
pop esi |
mov dword [edi-32], '.. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov ecx, [esp+28+8] |
mov word [edi-32+26], cx |
pop ecx |
jmp .writedircont |
;---------------------------------------------------------------- |
; |
; fs_FloppyWrite - LFN variant for writing to floppy |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
@@: |
push ERROR_ACCESS_DENIED |
fs_FloppyWrite.ret0: |
pop eax |
xor ebx, ebx |
ret |
fs_FloppyWrite.ret11: |
push 11 |
jmp fs_FloppyWrite.ret0 |
fs_FloppyWrite: |
cmp byte [esi], 0 |
jz @b |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz .ret11 |
pushad |
call fd_find_lfn |
jnc .found |
popad |
push ERROR_FILE_NOT_FOUND |
jmp .ret0 |
.found: |
; FAT does not support files larger than 4GB |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
.eof: |
popad |
push ERROR_END_OF_FILE |
jmp .ret0 |
@@: |
mov ebx, [ebx] |
.l1: |
; now edi points to direntry, ebx=start byte to write, |
; ecx=number of bytes to write, edx=data pointer |
; extend file if needed |
add ecx, ebx |
jc .eof ; FAT does not support files larger than 4GB |
push eax ; save directory cluster |
push 0 ; return value=0 |
call get_time_for_file |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
push dword [edi+28] ; save current file size |
cmp ecx, [edi+28] |
jbe .length_ok |
cmp ecx, ebx |
jz .length_ok |
call floppy_extend_file |
jnc .length_ok |
mov [esp+4], eax |
; floppy_extend_file can return two error codes: FAT table error or disk full. |
; First case is fatal error, in second case we may write some data |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax |
pop eax |
mov [esp+4+28], eax |
pop eax |
popad |
xor ebx, ebx |
ret |
.disk_full: |
; correct number of bytes to write |
mov ecx, [edi+28] |
cmp ecx, ebx |
ja .length_ok |
.ret: |
pop eax |
pop eax |
mov [esp+4+28], eax ; eax=return value |
pop eax |
sub edx, [esp+20] |
mov [esp+16], edx ; ebx=number of written bytes |
popad |
ret |
.length_ok: |
; save FAT & directory |
; note that directory must be saved first because save_flp_fat uses buffer at 0xD000 |
mov esi, [edi+28] |
movzx edi, word [edi+26] ; starting cluster |
mov eax, [esp+8] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err |
call save_flp_fat |
cmp [FDC_Status], 0 |
jz @f |
.device_err: |
mov byte [esp+4], 11 |
jmp .ret |
@@: |
; now ebx=start pos, ecx=end pos, both lie inside file |
sub ecx, ebx |
jz .ret |
call SetUserInterrupts |
.write_loop: |
; skip unmodified sectors |
cmp dword [esp], 0x200 |
jb .modify |
sub ebx, 0x200 |
jae .skip |
add ebx, 0x200 |
.modify: |
lea eax, [edi+31] ; current sector |
; get length of data in current sector |
push ecx |
sub ebx, 0x200 |
jb .hasdata |
neg ebx |
xor ecx, ecx |
jmp @f |
.hasdata: |
neg ebx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
; load sector if needed |
cmp dword [esp+4], 0 ; we don't need to read uninitialized data |
jz .noread |
cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten |
jz .noread |
cmp ecx, esi ; (same for the last sector) |
jz .noread |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jz @f |
.device_err2: |
pop ecx |
jmp .device_err |
@@: |
.noread: |
; zero uninitialized data if file was extended (because floppy_extend_file does not this) |
push eax ecx edi |
xor eax, eax |
mov ecx, 0x200 |
sub ecx, [esp+4+12] |
jbe @f |
mov edi, FDD_BUFF |
add edi, [esp+4+12] |
rep stosb |
@@: |
; zero uninitialized data in the last sector |
mov ecx, 0x200 |
sub ecx, esi |
jbe @f |
mov edi, FDD_BUFF |
add edi, esi |
rep stosb |
@@: |
pop edi ecx eax |
; copy new data |
push eax |
mov eax, edx |
neg ebx |
jecxz @f |
add ebx, FDD_BUFF+0x200 |
call memmove |
xor ebx, ebx |
@@: |
pop eax |
; save sector |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err2 |
add edx, ecx |
sub [esp], ecx |
pop ecx |
jz .done |
.skip: |
.next_cluster: |
movzx edi, word [edi*2+FLOPPY_FAT] |
sub esi, 0x200 |
jae @f |
xor esi, esi |
@@: |
sub dword [esp], 0x200 |
jae .write_loop |
and dword [esp], 0 |
jmp .write_loop |
.done: |
mov [fdc_irq_func], fdc_null |
jmp .ret |
floppy_extend_file.zero_size: |
xor eax, eax |
jmp floppy_extend_file.start_extend |
; extends file on floppy to given size (new data area is undefined) |
; in: edi->direntry, ecx=new size |
; out: CF=0 => OK, eax=0 |
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL) |
floppy_extend_file: |
push ecx |
; find the last cluster of file |
movzx eax, word [edi+26] ; first cluster |
mov ecx, [edi+28] |
jecxz .zero_size |
@@: |
sub ecx, 0x200 |
jbe @f |
mov eax, [eax*2+FLOPPY_FAT] |
and eax, 0xFFF |
jz .fat_err |
cmp eax, 0xFF8 |
jb @b |
.fat_err: |
pop ecx |
push ERROR_FAT_TABLE |
pop eax |
stc |
ret |
@@: |
push eax |
mov eax, [eax*2+FLOPPY_FAT] |
and eax, 0xFFF |
cmp eax, 0xFF8 |
pop eax |
jb .fat_err |
; set length to full number of sectors |
sub [edi+28], ecx |
.start_extend: |
pop ecx |
; now do extend |
push edx esi |
mov esi, FLOPPY_FAT+2*2 ; start scan from cluster 2 |
mov edx, 2847 ; number of clusters to scan |
.extend_loop: |
cmp [edi+28], ecx |
jae .extend_done |
; add new sector |
push ecx |
push edi |
.scan: |
mov ecx, edx |
mov edi, esi |
jecxz .disk_full |
push eax |
xor eax, eax |
repnz scasw |
pop eax |
jnz .disk_full |
mov word [edi-2], 0xFFF |
mov esi, edi |
mov edx, ecx |
sub edi, FLOPPY_FAT |
shr edi, 1 |
dec edi ; now edi=new cluster |
test eax, eax |
jz .first_cluster |
mov [FLOPPY_FAT+eax*2], di |
jmp @f |
.first_cluster: |
pop eax ; eax->direntry |
push eax |
mov [eax+26], di |
@@: |
mov eax, edi ; eax=new cluster |
pop edi ; edi->direntry |
pop ecx ; ecx=required size |
add dword [edi+28], 0x200 |
jmp .extend_loop |
.extend_done: |
mov [edi+28], ecx |
pop esi edx |
xor eax, eax ; CF=0 |
ret |
.disk_full: |
pop edi ecx |
pop esi edx |
stc |
push ERROR_DISK_FULL |
pop eax |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppySetFileEnd - set end of file on floppy |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppySetFileEnd: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz ret11 |
cmp byte [esi], 0 |
jnz @f |
.access_denied: |
push ERROR_ACCESS_DENIED |
jmp .ret |
@@: |
push edi |
call fd_find_lfn |
jnc @f |
pop edi |
push ERROR_FILE_NOT_FOUND |
.ret: |
pop eax |
jmp .doret |
@@: |
; must not be directory |
test byte [edi+11], 10h |
jz @f |
pop edi |
jmp .access_denied |
@@: |
; file size must not exceed 4 Gb |
cmp dword [ebx+4], 0 |
jz @f |
pop edi |
push ERROR_END_OF_FILE |
jmp .ret |
@@: |
push eax |
; set file modification date/time to current |
call fat_update_datetime |
mov eax, [ebx] |
cmp eax, [edi+28] |
jb .truncate |
ja .expand |
pop eax |
pushad |
call save_chs_sector |
popad |
pop edi |
xor eax, eax |
cmp [FDC_Status], 0 |
jz @f |
mov al, 11 |
@@: |
.doret: |
mov [fdc_irq_func], fdc_null |
ret |
.expand: |
push ecx |
push dword [edi+28] ; save old size |
mov ecx, eax |
call floppy_extend_file |
push eax ; return code |
jnc .expand_ok |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax ecx ecx edi edi |
jmp .doret |
.device_err: |
pop eax |
.device_err2: |
pop ecx ecx eax edi |
push 11 |
jmp .ret |
.disk_full: |
.expand_ok: |
; save directory & FAT |
mov eax, [edi+28] |
xchg eax, [esp+12] |
movzx edi, word [edi+26] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err |
call save_flp_fat |
cmp [FDC_Status], 0 |
jnz .device_err |
call SetUserInterrupts |
; now zero new data |
; edi = current cluster, [esp+12]=new size, [esp+4]=old size, [esp]=return code |
.zero_loop: |
sub dword [esp+4], 0x200 |
jae .next_cluster |
cmp dword [esp+4], -0x200 |
jz .noread |
lea eax, [edi+31] |
pusha |
call read_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .err_next |
.noread: |
mov ecx, [esp+4] |
neg ecx |
push edi |
mov edi, FDD_BUFF+0x200 |
add edi, [esp+8] |
xor eax, eax |
mov [esp+8], eax |
rep stosb |
pop edi |
lea eax, [edi+31] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jz .next_cluster |
.err_next: |
mov byte [esp], 11 |
.next_cluster: |
sub dword [esp+12], 0x200 |
jbe .expand_done |
movzx edi, word [FLOPPY_FAT+edi*2] |
jmp .zero_loop |
.expand_done: |
pop eax ecx ecx edi edi |
jmp .doret |
.truncate: |
mov [edi+28], eax |
push ecx |
movzx ecx, word [edi+26] |
test eax, eax |
jz .zero_size |
; find new last sector |
@@: |
sub eax, 0x200 |
jbe @f |
movzx ecx, word [FLOPPY_FAT+ecx*2] |
jmp @b |
@@: |
; we will zero data at the end of last sector - remember it |
push ecx |
; terminate FAT chain |
lea ecx, [FLOPPY_FAT+ecx+ecx] |
push dword [ecx] |
mov word [ecx], 0xFFF |
pop ecx |
and ecx, 0xFFF |
jmp .delete |
.zero_size: |
and word [edi+26], 0 |
push 0 |
.delete: |
; delete FAT chain starting with ecx |
; mark all clusters as free |
cmp ecx, 0xFF8 |
jae .deleted |
lea ecx, [FLOPPY_FAT+ecx+ecx] |
push dword [ecx] |
and word [ecx], 0 |
pop ecx |
and ecx, 0xFFF |
jmp .delete |
.deleted: |
mov edi, [edi+28] |
; save directory & FAT |
mov eax, [esp+8] |
pusha |
call save_chs_sector |
popa |
cmp [FDC_Status], 0 |
jnz .device_err2 |
call save_flp_fat |
cmp [FDC_Status], 0 |
jnz .device_err2 |
; zero last sector, ignore errors |
pop eax |
add eax, 31 |
and edi, 0x1FF |
jz .truncate_done |
call SetUserInterrupts |
pusha |
call read_chs_sector |
popa |
add edi, FDD_BUFF |
mov ecx, FDD_BUFF+0x200 |
sub ecx, edi |
push eax |
xor eax, eax |
rep stosb |
pop eax |
pusha |
call save_chs_sector |
popa |
.truncate_done: |
pop ecx eax edi |
xor eax, eax |
jmp .doret |
fs_FloppyGetFileInfo: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz ret11 |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 ; unsupported |
ret |
@@: |
push edi |
call fd_find_lfn |
jmp fs_GetFileInfo_finish |
ret11: |
mov eax, 11 |
ret |
fs_FloppySetFileInfo: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jnz ret11 |
cmp byte [esi], 0 |
jnz @f |
mov eax, 2 ; unsupported |
ret |
@@: |
push edi |
call fd_find_lfn |
jnc @f |
pop edi |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
@@: |
push eax |
call bdfe_to_fat_entry |
pop eax |
pusha |
call save_chs_sector |
popa |
pop edi |
xor eax, eax |
cmp [FDC_Status], al |
jz @f |
mov al, 11 |
@@: |
ret |
;---------------------------------------------------------------- |
; |
; fs_FloppyDelete - delete file or empty folder from floppy |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_FloppyDelete: |
call read_flp_fat |
cmp [FDC_Status], 0 |
jz @f |
push 11 |
jmp .pop_ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
; cannot delete root! |
.access_denied: |
push ERROR_ACCESS_DENIED |
.pop_ret: |
pop eax |
ret |
@@: |
and [fd_prev_sector], 0 |
and [fd_prev_prev_sector], 0 |
push edi |
call fd_find_lfn |
jnc .found |
pop edi |
push ERROR_FILE_NOT_FOUND |
jmp .pop_ret |
.found: |
cmp dword [edi], '. ' |
jz .access_denied2 |
cmp dword [edi], '.. ' |
jz .access_denied2 |
test byte [edi+11], 10h |
jz .dodel |
; we can delete only empty folders! |
push eax |
movzx eax, word [edi+26] |
push ebx |
pusha |
add eax, 31 |
call read_chs_sector |
popa |
mov ebx, FDD_BUFF + 2*0x20 |
.checkempty: |
cmp byte [ebx], 0 |
jz .empty |
cmp byte [ebx], 0xE5 |
jnz .notempty |
add ebx, 0x20 |
cmp ebx, FDD_BUFF + 0x200 |
jb .checkempty |
movzx eax, word [FLOPPY_FAT + eax*2] |
pusha |
add eax, 31 |
call read_chs_sector |
popa |
mov ebx, FDD_BUFF |
jmp .checkempty |
.notempty: |
pop ebx |
pop eax |
.access_denied2: |
pop edi |
jmp .access_denied |
.empty: |
pop ebx |
pop eax |
pusha |
call read_chs_sector |
popa |
.dodel: |
push eax |
movzx eax, word [edi+26] |
xchg eax, [esp] |
; delete folder entry |
mov byte [edi], 0xE5 |
; delete LFN (if present) |
.lfndel: |
cmp edi, FDD_BUFF |
ja @f |
cmp [fd_prev_sector], 0 |
jz .lfndone |
push [fd_prev_sector] |
push [fd_prev_prev_sector] |
pop [fd_prev_sector] |
and [fd_prev_prev_sector], 0 |
pusha |
call save_chs_sector |
popa |
pop eax |
pusha |
call read_chs_sector |
popa |
mov edi, FDD_BUFF+0x200 |
@@: |
sub edi, 0x20 |
cmp byte [edi], 0xE5 |
jz .lfndone |
cmp byte [edi+11], 0xF |
jnz .lfndone |
mov byte [edi], 0xE5 |
jmp .lfndel |
.lfndone: |
pusha |
call save_chs_sector |
popa |
; delete FAT chain |
pop eax |
test eax, eax |
jz .done |
@@: |
lea eax, [FLOPPY_FAT + eax*2] |
push dword [eax] |
and word [eax], 0 |
pop eax |
and eax, 0xFFF |
jnz @b |
.done: |
call save_flp_fat |
pop edi |
xor eax, eax |
ret |
; \end{diamond} |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/fs/parse_fn.inc |
---|
0,0 → 1,236 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;------------------------------------------------------------------------- |
; |
; File path partial substitution (according to configuration) |
; |
; |
; SPraid |
; |
;------------------------------------------------------------------------- |
$Revision$ |
iglobal |
; pointer to memory for path replace table, |
; size of one record is 128 bytes: 64 bytes for search pattern + 64 bytes for replace string |
; start with one entry: sys -> <sysdir> |
full_file_name_table dd sysdir_name |
.size dd 1 |
tmp_file_name_size dd 1 |
endg |
uglobal |
; Parser_params will initialize: sysdir_name = "sys", sysdir_path = <sysdir> |
sysdir_name rb 64 |
sysdir_path rb 64 |
tmp_file_name_table dd ? |
endg |
; use bx_from_load and init system directory /sys |
proc Parser_params |
locals |
buff db 4 dup(?) ; for test cd |
endl |
mov eax,[OS_BASE+0x10000+bx_from_load] |
mov ecx,sysdir_path |
mov [ecx-64],dword 'sys' |
cmp al,'r' ; if ram disk |
jnz @f |
mov [ecx],dword 'RD/?' |
mov [ecx+3],byte ah |
mov [ecx+4],byte 0 |
ret |
@@: |
cmp al,'m' ; if ram disk |
jnz @f |
mov [ecx],dword 'CD?/' ; if cd disk {m} |
mov [ecx+4],byte '1' |
mov [ecx+5],dword '/KOL' |
mov [ecx+9],dword 'IBRI' |
mov [ecx+13],byte 0 |
.next_cd: |
mov [ecx+2],byte ah |
inc ah |
cmp ah,'5' |
je .not_found_cd |
lea edx,[buff] |
pushad |
stdcall read_file,read_firstapp,edx,0,4 |
popad |
cmp [edx],dword 'MENU' |
jne .next_cd |
jmp .ok |
@@: |
sub al,49 |
mov [ecx],dword 'HD?/' ; if hard disk |
mov [ecx+2],byte al |
mov [ecx+4],byte ah |
mov [ecx+5],dword '/KOL' |
mov [ecx+9],dword 'IBRI' |
mov [ecx+13],byte 0 |
.ok: |
.not_found_cd: |
ret |
endp |
proc load_file_parse_table |
stdcall kernel_alloc,0x1000 |
mov [tmp_file_name_table],eax |
mov edi,eax |
mov esi,sysdir_name |
mov ecx,128/4 |
rep movsd |
invoke ini.enum_keys,conf_fname,conf_path_sect,get_every_key |
mov eax,[tmp_file_name_table] |
mov [full_file_name_table],eax |
mov eax,[tmp_file_name_size] |
mov [full_file_name_table.size],eax |
ret |
endp |
uglobal |
def_val_1 db 0 |
endg |
proc get_every_key stdcall, f_name, sec_name, key_name |
mov esi, [key_name] |
mov ecx, esi |
cmp byte [esi], '/' |
jnz @f |
inc esi |
@@: |
mov edi, [tmp_file_name_size] |
shl edi, 7 |
cmp edi, 0x1000 |
jae .stop_parse |
add edi, [tmp_file_name_table] |
lea ebx, [edi+64] |
@@: |
cmp edi, ebx |
jae .skip_this_key |
lodsb |
test al, al |
jz @f |
or al, 20h |
stosb |
jmp @b |
@@: |
stosb |
invoke ini.get_str, [f_name],[sec_name],ecx,ebx,64,def_val_1 |
cmp byte [ebx], '/' |
jnz @f |
lea esi, [ebx+1] |
mov edi, ebx |
mov ecx, 63 |
rep movsb |
@@: |
push ebp |
mov ebp, [tmp_file_name_table] |
mov ecx, [tmp_file_name_size] |
jecxz .noreplace |
mov eax, ecx |
dec eax |
shl eax, 7 |
add ebp, eax |
.replace_loop: |
mov edi, ebx |
mov esi, ebp |
@@: |
lodsb |
test al, al |
jz .doreplace |
mov dl, [edi] |
inc edi |
test dl, dl |
jz .replace_loop_cont |
or dl, 20h |
cmp al, dl |
jz @b |
jmp .replace_loop_cont |
.doreplace: |
cmp byte [edi], 0 |
jz @f |
cmp byte [edi], '/' |
jnz .replace_loop_cont |
@@: |
lea esi, [ebp+64] |
call .replace |
jc .skip_this_key2 |
.replace_loop_cont: |
sub ebp, 128 |
loop .replace_loop |
.noreplace: |
pop ebp |
inc [tmp_file_name_size] |
.skip_this_key: |
xor eax, eax |
inc eax |
ret |
.skip_this_key2: |
pop ebp |
jmp .skip_this_key |
.stop_parse: |
xor eax, eax |
ret |
endp |
proc get_every_key.replace |
; in: ebx->destination, esi->first part of name, edi->second part of name |
; maximum length is 64 bytes |
; out: CF=1 <=> overflow |
; 1) allocate temporary buffer in stack |
sub esp, 64 |
; 2) save second part of name to temporary buffer |
push esi |
lea esi, [esp+4] ; esi->tmp buffer |
xchg esi, edi ; edi->tmp buffer, esi->source |
@@: |
lodsb |
stosb |
test al, al |
jnz @b |
; 3) copy first part of name to destination |
pop esi |
mov edi, ebx |
@@: |
lodsb |
test al, al |
jz @f |
stosb |
jmp @b |
@@: |
; 4) restore second part of name from temporary buffer to destination |
; (may cause overflow) |
lea edx, [ebx+64] ; limit of destination |
mov esi, esp |
@@: |
cmp edi, edx |
jae .overflow |
lodsb |
stosb |
test al, al |
jnz @b |
; all is OK |
add esp, 64 ; CF is cleared |
ret |
.overflow: |
; name is too long |
add esp, 64 |
stc |
ret |
endp |
Property changes: |
Added: svn:keywords |
+Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/fs/. |
---|
Property changes: |
Added: svn:ignore |
+*.mnt |
+lang.inc |
+*.bat |
+out.txt |
+scin* |
+*.obj |