0,0 → 1,3967 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; FAT32.INC ;; |
;; ;; |
;; FAT16/32 functions for MenuetOS ;; |
;; ;; |
;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;; |
;; ;; |
;; See file COPYING for details ;; |
;; 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 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
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] |
|
cluster dd 0 ; used by file_write,makedir,append |
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 |
|
sector_tmp dd 0 ; used by rename,append,file_write |
entry_pos dd 0 ; used by rename,append,file_write |
|
old_filesize dd 0 ; used by append |
new_filepos dd 0 ; used by append |
bytes2write dd 0 ; used by append |
|
cache_search_start dd 0 ; used by find_empty_slot |
|
fat_in_cache dd -1 |
fat_cache: times 512 db 0 |
|
uglobal |
Sector512: ; label for dev_hdcd.inc |
buffer: times 512 db 0 |
deltree_buffer: times 512 db 0 |
endg |
|
iglobal |
NewDirEntry1 db ". ",0x10 |
times 20 db 0 |
NewDirEntry2 db ".. ",0x10 |
times 20 db 0 |
endg |
|
uglobal |
dir_entry: times 32 db 0 |
|
startpath: times 255 db 0 |
|
fat16_root db 0 ; flag for fat16 rootdir |
f_del db 0 ; 1=overwrite fat entry |
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,[0x3000] |
shl eax,5 |
mov eax,[eax+0x3000+TASKDATA.pid] |
mov [hd1_status],eax |
pop eax |
sti |
ret |
;******************************************** |
reserve_hd_channel: |
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_1 |
.reserve_ok_1: |
mov [IDE_Channel_1],1 |
ret |
.reserve_ok_2: |
mov [IDE_Channel_2],1 |
ret |
|
free_hd_channel: |
cmp [hdbase], 0x1F0 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
mov [IDE_Channel_1],0 |
ret |
.IDE_Channel_2: |
mov [IDE_Channel_2],0 |
ret |
;******************************************** |
clear_hd_cache: |
|
push eax ecx edi |
mov edi,0x600000 |
mov ecx,16384 |
xor eax,eax |
cld |
rep stosd ; clear hd cache with 0 |
mov [cache_search_start],eax |
mov [fat_in_cache],-1 |
mov [fat_change],0 |
pop edi ecx eax |
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 [fat_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 [fat_type],16 |
jne sfc_test32 |
|
cmp [f_del],1 ; overwrite previous value? |
je sfc_set16 ; yes |
cmp word [ebx+esi],0 ; is cluster free? |
je sfc_set16 ; yes |
mov dword [8*0x100000],0xffffff |
mov edx,[ebx+esi] ; get old value |
jmp sfc_nonzero |
|
sfc_set16: |
xchg [ebx+esi],dx ; save new value and get old value |
jmp sfc_write |
|
sfc_test32: |
mov eax,[fatMASK] |
cmp [f_del],1 ; overwrite previous value? |
je sfc_set32 ; yes |
test eax,[ebx+esi] ; is cluster free? |
je sfc_set32 ; yes |
mov dword [8*0x100000],0xffffff |
mov edx,[ebx+esi] ; get old value |
jmp sfc_nonzero |
|
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 [fat_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: |
;----------------------------------------------------------- |
; input : EAX = # cluster for start the searching |
; 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 |
|
gff_test: |
cmp eax,[LAST_CLUSTER] ; if above last cluster start at cluster 2 |
jbe gff_in_range |
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: |
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 [fat_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 |
|
|
analyze_directory_to_write: |
;----------------------------------------------------------- |
; input : EAX = first cluster of the directory |
; output : IF CARRY=0 EAX = sector where the empty pos is found |
; EBX = pointer in buffer |
; [buffer .. buffer+511] |
; ECX,EDX,ESI,EDI not changed |
; IF CARRY=1 disk full or fat corrupted |
; Note : if cluster=0 it's changed to read rootdir |
;----------------------------------------------------------- |
push ecx edx edi |
|
adw_new_cluster: |
mov [cluster_tmp],eax |
mov [fat16_root],0 |
cmp eax,[LAST_CLUSTER] |
ja adw_not_found ; too big cluster number, something is wrong |
cmp eax,2 |
jnb adw_data_cluster |
|
mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir |
cmp [fat_type],16 |
jne adw_data_cluster |
mov eax,[ROOT_START] |
mov edx,[ROOT_SECTORS] |
mov [fat16_root],1 ; flag for fat16 rootdir |
jmp adw_new_sector |
|
adw_data_cluster: |
sub eax,2 |
mov edx,[SECTORS_PER_CLUSTER] |
imul eax,edx |
add eax,[DATA_START] |
|
adw_new_sector: |
mov ebx,buffer |
call hd_read |
cmp [hd_error],0 |
jne adw_not_found |
|
mov ecx,512/32 ; count of dir entrys per sector = 16 |
|
adw_analyze: |
cmp byte [ebx],0x00 ; is free entry? |
je adw_found ; yes |
cmp byte [ebx],0xe5 ; is deleted entry? |
je adw_found ; yes |
add ebx,32 ; position of next dir entry |
dec ecx |
jnz adw_analyze |
|
inc eax ; next sector |
dec edx |
jne adw_new_sector |
cmp [fat16_root],1 ; end of fat16 rootdir |
je adw_not_found |
|
mov eax,[cluster_tmp] |
call get_FAT ; get next cluster |
cmp [hd_error],0 |
jne adw_not_found |
|
cmp eax,2 ; incorrect fat chain? |
jb adw_not_found ; yes |
cmp eax,[fatRESERVED] ; is it end of directory? |
jb adw_new_cluster ; no. analyse it |
|
mov eax,2 ; this block of code add a new cluster |
call get_free_FAT ; for the directory because the directory |
jc adw_not_found ; is full |
|
mov edx,[fatEND] ; new end for directory |
call set_FAT |
cmp [hd_error],0 |
jne adw_not_found |
|
push eax ; save new cluster |
mov edx,eax |
mov eax,[cluster_tmp] ; change last cluster to point new cluster |
mov [f_del],1 |
call set_FAT |
cmp [hd_error],0 |
jne adw_not_found_1 |
|
mov [f_del],0 |
|
mov ecx,-1 ; remove 1 cluster from free disk space |
call add_disk_free_space |
cmp [hd_error],0 |
jne adw_not_found_1 |
|
mov ecx,512/4 |
xor eax,eax |
mov edi,buffer |
cld |
rep stosd ; clear new directory cluster |
pop eax |
|
sub eax,2 |
mov ecx,[SECTORS_PER_CLUSTER] |
imul eax,ecx |
add eax,[DATA_START] |
mov ebx,buffer |
push eax ; save sector number |
|
adw_set_empty_directory: |
call hd_write |
cmp [hd_error],0 |
jne adw_not_found_1 |
|
inc eax ; next sector |
dec ecx |
jnz adw_set_empty_directory |
|
pop eax |
|
adw_found: |
pop edi edx ecx |
clc ; free space found |
ret |
adw_not_found_1: |
add esp,4 |
adw_not_found: |
pop edi edx ecx |
stc ; free space not 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 [fat_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 |
|
|
set_data_cluster: |
;----------------------------------------------------------- |
; input : EAX = cluster |
; EBX = pointer to buffer |
; output : if CARRY=0 ok |
; if CARRY=1 cluster out of range |
;----------------------------------------------------------- |
push eax ebx edx |
|
cmp eax,[LAST_CLUSTER] |
ja sdc_error ; too big cluster number, something is wrong |
sub eax,2 |
jb sdc_error ; don't allow rootdir write |
|
mov edx,[SECTORS_PER_CLUSTER] |
imul eax,edx |
add eax,[DATA_START] |
|
sdc_write: |
call hd_write |
cmp [hd_error],0 |
jne sdc_error |
|
add ebx,512 ; update pointer |
inc eax |
dec edx |
jnz sdc_write |
pop edx ebx eax |
clc |
ret |
|
sdc_error: |
pop edx ebx 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 |
|
|
makedir: |
;----------------------------------------------------- |
; input : eax = directory name |
; edx = path |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 8 - disk full |
; 10 - access denied |
; Note : can only make one directory at time |
;----------------------------------------------------- |
cmp [fat_type],0 |
jnz make_dir_fat_ok |
mov eax,ERROR_UNKNOWN_FS |
ret |
|
make_dir_fat_ok: |
; call reserve_hd1 |
|
pushad |
|
mov ebx,edx |
call get_cluster_of_a_path |
jnc make_dir_found_path |
cmp [hd_error],0 |
jne make_dir_error_1 |
|
make_dir_path_not_found: |
popad |
call update_disk ; write all of cache and fat to hd |
cmp [hd_error],0 |
jne make_dir_error_2 |
|
mov [hd1_status],0 |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
|
make_dir_disk_full: |
cmp [hd_error],0 |
jne make_dir_error_1 |
popad |
call update_disk ; write all of cache and fat to hd |
cmp [hd_error],0 |
jne make_dir_error_2 |
|
mov [hd1_status],0 |
mov eax,ERROR_DISK_FULL |
ret |
|
make_dir_already_exist: |
cmp [hd_error],0 |
jne make_dir_error_1 |
mov eax,[cluster] ; directory cluster |
xor edx,edx ; free |
mov [f_del],1 |
call set_FAT |
cmp [hd_error],0 |
jne make_dir_error_1 |
|
mov [f_del],0 |
|
popad |
call update_disk ; write all of cache and fat to hd |
make_dir_error_2: |
mov [hd1_status],0 |
mov eax,ERROR_ACCESS_DENIED |
ret |
|
make_dir_error_1: |
popad |
jmp make_dir_error_2 |
|
make_dir_error_3: |
add esp,4 |
jmp make_dir_error_1 |
|
make_dir_found_path: |
cmp eax,[ROOT_CLUSTER] |
jnz make_dir_not_root |
xor eax,eax |
|
make_dir_not_root: |
mov ecx,eax ; directorys start cluster |
mov word [NewDirEntry2+26],cx ; 16 bits low of cluster |
shr ecx,16 |
mov word [NewDirEntry2+20],cx ; 16 bits high of cluster (=0 fat16) |
|
push eax ; save parent directory cluster |
mov eax,2 |
call get_free_FAT |
mov [cluster],eax ; first free cluster |
pop eax |
jc make_dir_disk_full |
|
push eax |
mov eax,[cluster] ; directory cluster |
mov edx,[fatEND] ; end for directory |
call set_FAT |
cmp [hd_error],0 |
jne make_dir_error_3 |
pop eax |
|
mov ebx,PUSHAD_EAX ; dir name |
push eax |
call analyze_directory ; check if directory already exist |
cmp [hd_error],0 |
jne make_dir_error_1 |
|
pop eax |
jnc make_dir_already_exist ; need to free allocated cluster! |
|
call analyze_directory_to_write |
jc make_dir_already_exist ; need to free allocated cluster! |
|
mov esi,PUSHAD_EAX ; dir name |
mov edi,ebx ; pointer in buffer |
mov ecx,11 |
cld |
rep movsb |
|
mov dword [ebx+28],0 ; dir size is always 0 |
mov ecx,[cluster] |
mov [ebx+26],cx ; 16 bits low of cluster |
mov word [NewDirEntry1+26],cx |
shr ecx,16 |
mov [ebx+20],cx ; 16 bits high of cluster (=0 fat16) |
mov word [NewDirEntry1+20],cx |
mov byte [ebx+11],0x10 ; attribute = directory |
|
call set_current_time_for_entry |
mov ecx,[ebx+22] |
mov dword [NewDirEntry1+22],ecx |
mov dword [NewDirEntry2+22],ecx |
|
mov ebx,buffer ; save the directory name,length,cluster |
call hd_write |
cmp [hd_error],0 |
jne make_dir_error_1 |
|
mov ecx,512/4 |
xor eax,eax |
mov edi,buffer |
cld |
rep stosd ; clear new directory cluster |
|
mov eax,[cluster] ; new directory cluster |
sub eax,2 |
mov edx,[SECTORS_PER_CLUSTER] |
imul eax,edx |
add eax,[DATA_START] |
mov ebx,buffer |
add eax,edx ; start from last sector |
|
dir_set_empty_directory: |
dec eax ; next sector |
cmp edx,1 ; is first directory sector? |
jnz not_first_sector ; no. write empty sector |
mov esi,NewDirEntry1 |
mov edi,buffer |
mov ecx,64/4 |
cld |
rep movsd ; copy 2 first directory entrys "." and ".." |
|
not_first_sector: |
call hd_write |
cmp [hd_error],0 |
jne make_dir_error_1 |
|
dec edx |
jnz dir_set_empty_directory |
|
mov ecx,-1 ; remove 1 cluster from free disk space |
call add_disk_free_space |
cmp [hd_error],0 |
jne make_dir_error_1 |
|
popad |
call update_disk ; write all of cache and fat to hd |
cmp [hd_error],0 |
jne make_dir_error_2 |
mov [hd1_status],0 |
xor eax,eax |
ret |
|
|
removedir: |
;----------------------------------------------------- |
; input : eax = file/directory name |
; edx = path |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 10 - access denied |
;----------------------------------------------------- |
cmp [fat_type],0 |
jnz remove_dir_fat_ok |
mov eax,ERROR_UNKNOWN_FS |
ret |
|
remove_dir_fat_ok: |
; call reserve_hd1 |
|
push edi |
mov edi,1 ; allow directory remove |
call file_delete |
cmp [hd_error],0 |
jne @f |
|
pop edi |
|
call update_disk ; write all of cache and fat to hd |
@@: |
mov [hd1_status],0 |
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 [fat_type],32 ; free disk space only used by fat32 |
jne add_dfs_no |
|
push eax ebx |
mov eax,[ADR_FSINFO] |
mov ebx,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 |
call hd_write |
cmp [hd_error],0 |
jne add_not_fs |
|
add_not_fs: |
pop ebx eax |
|
add_dfs_no: |
ret |
|
|
file_append: |
;----------------------------------------------------- |
; input : eax = file name |
; edx = path |
; ecx = pointer to buffer |
; ebx = bytes to write (0 = truncate file) |
; esi = start position (-1 = end of file) |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 6 - end of file |
; 8 - disk full |
; 9 - fat table corrupted |
; 10 - access denied |
; ebx = bytes written |
;----------------------------------------------------- |
cmp [fat_type],0 |
jnz append_fat_ok |
mov eax,ERROR_UNKNOWN_FS |
ret |
|
append_fat_ok: |
; call reserve_hd1 |
|
pushad |
|
mov ebx,edx |
call get_cluster_of_a_path |
jc append_not_found |
|
mov ebx,PUSHAD_EAX ; file name |
call analyze_directory |
jc append_not_found |
|
mov [sector_tmp],eax |
mov [entry_pos],ebx |
|
test byte [ebx+11],0x10 ; is it directory? |
jnz append_access ; yes |
|
mov ecx,[ebx+28] ; file size |
mov edi,PUSHAD_ESI ; write position |
cmp edi,-1 ; -1 = eof |
jnz append_inside_file |
mov edi,ecx ; file size |
|
append_inside_file: |
cmp edi,ecx ; start above old file size? |
ja append_eof ; yes |
|
mov [old_filesize],ecx |
mov [new_filepos],edi |
|
mov ecx,PUSHAD_EBX ; bytes to write |
test ecx,ecx ; truncate? |
jz append_truncate ; yes |
|
mov [bytes2write],ecx ; bytes to write |
mov esi,PUSHAD_ECX ; pointer to buffer |
mov eax,[ebx+20-2] ; FAT entry |
mov ax,[ebx+26] |
and eax,[fatMASK] |
jnz append_find_pos ; first cluster <> 0 |
|
mov eax,2 |
call get_free_FAT |
jc append_disk_full |
mov ecx,eax ; set files first cluster |
mov [ebx+26],cx ; 16 bits low of cluster |
shr ecx,16 |
mov [ebx+20],cx ; 16 bits high of cluster (=0 fat16) |
mov edx,[fatEND] ; new end for cluster chain |
call set_FAT |
cmp [hd_error],0 |
jne append_access |
|
push eax ; save first cluster |
mov eax,[sector_tmp] |
mov ebx,buffer |
call hd_write ; write new file entry back to disk |
cmp [hd_error],0 |
jne append_access_1 |
|
pop eax |
|
append_remove_free: |
mov ecx,-1 ; remove 1 cluster from free disk space |
call add_disk_free_space ; Note: uses buffer |
cmp [hd_error],0 |
jne append_access |
|
append_found_cluster: |
mov [cluster],eax |
sub eax,2 |
mov ecx,[SECTORS_PER_CLUSTER] |
imul eax,ecx |
add eax,[DATA_START] |
xor edi,edi |
|
append_new_sector: |
cmp [hd_error],0 |
jne append_access |
push ecx |
mov ecx,[bytes2write] ; bytes left in buffer |
mov ebx,512 |
sub ebx,edi ; bytes left in sector |
cmp ecx,ebx |
jb append_bytes_ok |
mov ecx,ebx |
|
append_bytes_ok: |
cmp ecx,512 ; overwrite full sector? |
jz append_full_sector ; yes |
mov ebx,buffer ; overwrite part of sector |
call hd_read ; read old sector |
cmp [hd_error],0 |
jne append_access_1 |
|
append_full_sector: |
sub [bytes2write],ecx |
add [new_filepos],ecx |
add edi,buffer |
cld |
rep movsb |
pop ecx |
|
mov ebx,buffer |
call hd_write |
cmp [hd_error],0 |
jne append_access |
|
cmp [bytes2write],0 ; is all done? |
jz append_done |
xor edi,edi |
inc eax |
dec ecx |
jnz append_new_sector |
|
mov eax,[cluster] |
call get_FAT |
cmp [hd_error],0 |
jne append_access |
|
cmp eax,2 |
jb append_fat |
cmp eax,[LAST_CLUSTER] |
jbe append_found_cluster |
|
append_alloc_cluster: |
mov eax,2 ; ToDo: use temp array to keep track |
call get_free_FAT ; of last free cluster |
jc append_disk_full |
push eax ; save new cluster |
mov edx,[fatEND] ; new end for cluster chain |
call set_FAT |
cmp [hd_error],0 |
jne append_access_1 |
|
mov edx,eax |
mov eax,[cluster] |
mov [f_del],1 |
call set_FAT ; update previous cluster |
cmp [hd_error],0 |
jne append_access_1 |
|
mov [f_del],0 |
pop eax |
jmp append_remove_free |
|
append_find_pos: |
call find_filepos |
mov [cluster],ebx |
jnc append_new_sector |
test edi,edi |
jz append_alloc_cluster |
|
append_fat: |
mov eax,ERROR_FAT_TABLE |
jmp append_ret_code |
|
append_disk_full: |
cmp [hd_error],0 |
jne append_access |
mov eax,ERROR_DISK_FULL |
jmp append_ret_code |
|
append_done: |
xor eax,eax |
|
append_ret_code: |
mov PUSHAD_EAX,eax ; return code |
|
mov eax,[sector_tmp] ; update directory entry |
mov ebx,buffer |
call hd_read |
cmp [hd_error],0 |
jne append_access |
|
mov ebx,[entry_pos] |
mov ecx,[new_filepos] |
cmp ecx,[old_filesize] ; is file pos above old size? |
jbe append_size_ok ; no |
mov [ebx+28],ecx ; new file size |
|
append_size_ok: |
call set_current_time_for_entry |
mov ebx,buffer |
call hd_write ; write new file entry back to disk |
cmp [hd_error],0 |
jne append_access |
|
sub ecx,PUSHAD_ESI ; start position |
mov PUSHAD_EBX,ecx ; bytes written |
popad |
call update_disk ; write all of cache and fat to hd |
cmp [hd_error],0 |
jne append_access_2 |
|
mov [hd1_status],0 |
ret |
|
append_eof: |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_END_OF_FILE |
ret |
|
append_not_found: |
cmp [hd_error],0 |
jne append_access |
popad |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
append_access_1: |
add esp,4 |
append_access: |
popad |
append_access_2: |
mov [hd1_status],0 |
xor ebx,ebx |
mov eax,ERROR_ACCESS_DENIED |
ret |
|
append_truncate: |
mov edx,[ebx+20-2] ; FAT entry |
mov dx,[ebx+26] |
and edx,[fatMASK] |
mov [ebx+28],edi ; set new file size |
test edi,edi ; 0 length file? |
jnz truncate_save_size ; no |
mov [ebx+20],di ; FAT entry = 0 |
mov [ebx+26],di |
|
truncate_save_size: |
call set_current_time_for_entry |
mov ebx,buffer |
call hd_write |
cmp [hd_error],0 |
jne append_access |
|
mov eax,edx ; first cluster |
test edi,edi ; 0 length file? |
jz truncate_clear_chain |
|
imul esi,[SECTORS_PER_CLUSTER],512 ; esi = cluster size in bytes |
|
truncate_new_cluster: |
cmp eax,2 ; incorrect fat chain? |
jb truncate_eof ; yes |
cmp eax,[fatRESERVED] ; is it end of file? |
jnb truncate_eof ; yes |
sub edi,esi |
jbe truncate_pos_found |
call get_FAT ; get next cluster |
cmp [hd_error],0 |
jne append_access |
|
jmp truncate_new_cluster |
|
truncate_pos_found: |
mov edx,[fatEND] ; new end for cluster chain |
mov [f_del],1 |
call set_FAT |
cmp [hd_error],0 |
jne append_access |
|
mov [f_del],0 |
mov eax,edx ; clear rest of chain |
|
truncate_clear_chain: |
call clear_cluster_chain |
cmp [hd_error],0 |
jne append_access |
|
truncate_eof: |
popad |
call update_disk ; write all of cache and fat to hd |
cmp [hd_error],0 |
jne append_access_2 |
|
mov [hd1_status],0 |
xor ebx,ebx |
xor eax,eax |
ret |
|
|
find_filepos: |
;----------------------------------------------------- |
; input : eax = first cluster |
; edi = bytes to skip over (start position) |
; output : if CARRY=0 file position found |
; if CARRY=1 end of file found |
; eax = current file sector |
; ebx = last cluster |
; ecx = sector count in last cluster |
; edi = bytes to skip over (sector position) |
;----------------------------------------------------- |
push esi |
mov ecx,[SECTORS_PER_CLUSTER] |
imul esi,ecx,512 ; esi = cluster size in bytes |
mov ebx,eax |
|
filepos_new_cluster: |
cmp eax,2 ; incorrect fat chain? |
jb filepos_eof ; yes |
cmp eax,[fatRESERVED] ; is it end of file? |
jnb filepos_eof ; yes |
|
mov ebx,eax |
cmp edi,esi ; skip over full cluster? |
jb filepos_cluster_ok ; no |
|
sub edi,esi |
call get_FAT ; get next cluster |
cmp [hd_error],0 |
jne filepos_eof |
|
jmp filepos_new_cluster |
|
filepos_cluster_ok: |
sub eax,2 |
imul eax,ecx |
add eax,[DATA_START] |
|
filepos_new_sector: |
cmp edi,512 ; skip over full sector? |
jb filepos_sector_ok ; no |
sub edi,512 |
inc eax |
dec ecx |
jnz filepos_new_sector |
|
filepos_eof: |
pop esi |
stc |
ret |
|
filepos_sector_ok: |
pop esi |
clc |
ret |
|
|
file_write: |
;-------------------------------------------------------------------------- |
; INPUT : user-reg register-in-this meaning symbol-in-this-routine |
; |
; EAX EDI system call to write / |
; EBX EAX (PAR0) pointer to file-name PAR0 |
; EDX ECX (PAR1) pointer to buffer PAR1 |
; ECX EBX (PAR2) file size PAR2 |
; ESI EDX (PAR3) pointer to path PAR3 |
; |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 8 - disk full |
; 10 - access denied |
;-------------------------------------------------------------------------- |
cmp [fat_type],0 |
jnz fat_ok_for_writing |
mov eax,ERROR_UNKNOWN_FS |
ret |
|
fat_ok_for_writing: |
; call reserve_hd1 |
|
pushad |
|
xor edi,edi ; don't allow directory remove |
call file_delete ; try to delete the file first |
cmp [hd_error],0 |
jne exit_write_access_1 |
|
test eax,eax |
jz old_deleted ; deleted ok |
cmp eax,ERROR_FILE_NOT_FOUND |
jnz exit_write_access ; it exist but can't delete |
|
old_deleted: |
mov ebx,PUSHAD_EDX |
call get_cluster_of_a_path |
jnc found_directory_for_writing |
cmp [hd_error],0 |
jne exit_write_access |
|
exit_writing_with_error: |
popad |
call update_disk ; write all of cache and fat to hd |
cmp [hd_error],0 |
jne exit_write_access_2 |
|
mov [hd1_status],0 |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
|
exit_writing_disk_full_clear: |
cmp [hd_error],0 |
jne exit_write_access_1 |
mov eax,[sector_tmp] |
mov ebx,buffer |
call hd_read ; read directory sector |
cmp [hd_error],0 |
jne exit_write_access_1 |
|
mov edx,[entry_pos] |
mov byte [edx],0xe5 ; mark as deleted |
call hd_write |
cmp [hd_error],0 |
jne exit_write_access_1 |
|
mov eax,[edx+20-2] ; FAT entry |
mov ax,[edx+26] |
and eax,[fatMASK] |
call clear_cluster_chain |
|
exit_writing_disk_full: |
cmp [hd_error],0 |
jne exit_write_access_1 |
popad |
call update_disk ; write all of cache and fat to hd |
cmp [hd_error],0 |
jne exit_write_access_2 |
mov [hd1_status],0 |
mov eax,ERROR_DISK_FULL |
ret |
|
exit_write_access: |
popad |
call update_disk ; write all of cache and fat to hd |
mov [hd1_status],0 |
mov eax,ERROR_ACCESS_DENIED |
ret |
|
exit_write_access_1: |
popad |
exit_write_access_2: |
mov [hd1_status],0 |
mov eax,ERROR_ACCESS_DENIED |
ret |
|
found_directory_for_writing: |
call analyze_directory_to_write |
jc exit_writing_disk_full |
|
mov [sector_tmp],eax |
mov [entry_pos],ebx |
push eax ; save directory sector |
mov eax,2 |
call get_free_FAT |
mov [cluster],eax ; first free cluster |
pop eax |
jc exit_writing_disk_full |
|
mov esi,PUSHAD_EAX ; file name |
mov edi,ebx ; pointer in buffer |
mov ecx,11 |
cld |
rep movsb |
|
mov esi,PUSHAD_EBX ; file size (bytes left) |
mov [ebx+28],esi ; file size |
mov ecx,[cluster] |
mov [ebx+26],cx ; 16 bits low of cluster |
shr ecx,16 |
mov [ebx+20],cx ; 16 bits high of cluster (=0 fat16) |
mov byte [ebx+11],0x20 ; attribute = archive |
|
call set_current_time_for_entry |
|
mov ebx,buffer ; save the directory name,length,cluster |
call hd_write |
cmp [hd_error],0 |
jne exit_write_access_1 |
|
imul edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes |
xor ecx,ecx ; cluster count |
mov ebx,PUSHAD_ECX ; ebx = buffer |
|
hd_new_block_write: |
|
mov eax,[cluster] ; eax = block |
call set_data_cluster |
cmp [hd_error],0 |
jne exit_write_access_1 |
|
sub esi,edi ; sub wrote bytes |
jbe file_saved_OK ; end if all done |
add ebx,edi ; update buffer position |
|
inc eax |
call get_free_FAT ; next free in FAT |
jc exit_writing_disk_full_clear |
|
mov edx,eax |
xchg eax,[cluster] ; get old cluster and save new cluster |
call set_FAT ; add it in cluster chain |
cmp [hd_error],0 |
jne exit_write_access_1 |
|
dec ecx ; update cluster count |
jmp hd_new_block_write |
|
file_saved_OK: |
|
mov edx,[fatEND] ; new end for cluster chain |
call set_FAT |
cmp [hd_error],0 |
jne exit_write_access_1 |
|
dec ecx ; update cluster count |
|
call add_disk_free_space ; remove clusters from free disk space |
cmp [hd_error],0 |
jne exit_write_access_1 |
|
popad |
call update_disk ; write all of cache and fat to hd |
cmp [hd_error],0 |
jne exit_write_access_2 |
mov [hd1_status],0 |
xor eax,eax |
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 [fat_type],0 |
jnz 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 [fat_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 |
|
|
file_delete: |
;----------------------------------------------------- |
; input : eax = file/directory name |
; edx = path |
; edi = 1 - allow directory remove else don't remove directory |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 10 - access denied |
;----------------------------------------------------- |
cmp [fat_type],0 |
jnz file_del_fat_ok |
mov eax,ERROR_UNKNOWN_FS |
ret |
|
file_del_fat_ok: |
pushad |
|
mov ebx,edx |
call get_cluster_of_a_path |
jc file_to_delete_not_found |
|
mov ebx,PUSHAD_EAX ; file/directory name |
call analyze_directory |
jc file_to_delete_not_found |
|
test byte [ebx+11],0x10 ; is it directory? |
jz delete_notdir ; no. it's file |
cmp edi,1 ; allow directory remove |
jnz delete_no_access ; no |
|
push eax ; save directory sector |
mov eax,[ebx+20-2] ; first cluster of file |
mov ax,[ebx+26] ; 0 length files start cluster = 0 |
and eax,[fatMASK] |
xor ebp,ebp ; counter for directory deepnes |
call clear_directory |
pop eax |
jc delete_no_access |
|
push ebx ; save directory pointer in buffer |
mov ebx,buffer |
call hd_read ; read directory sector |
cmp [hd_error],0 |
jne delete_no_access_1 |
pop ebx |
|
delete_notdir: |
call delete_entry_name |
cmp [hd_error],0 |
jne delete_no_access |
|
mov eax,ecx ; first cluster of file |
call clear_cluster_chain |
cmp [hd_error],0 |
jne delete_no_access |
|
popad |
xor eax,eax |
ret |
|
delete_no_access_1: |
add esp,4 |
delete_no_access: |
popad |
mov eax,ERROR_ACCESS_DENIED |
ret |
|
file_to_delete_not_found: |
cmp [hd_error],0 |
jne delete_no_access |
popad |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
|
|
clear_cluster_chain: |
;----------------------------------------------------- |
; input : eax = first cluster |
;----------------------------------------------------- |
push eax ecx edx |
xor ecx,ecx ; cluster count |
mov [f_del],1 ; delete on |
|
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: |
mov [f_del],0 |
pop edx ecx eax |
ret |
|
|
clear_directory: |
;----------------------------------------------------- |
; input : eax = directory cluster |
; ebp = directory deepnes |
; Note : use recursive call |
;----------------------------------------------------- |
pushad |
inc ebp |
cmp ebp,64 ; if over 63 directory deep |
jnb clear_error ; something must be wrong |
|
clear_new_cluster: |
cmp eax,[LAST_CLUSTER] |
ja clear_end |
cmp eax,[ROOT_CLUSTER] ; don't remove root cluster |
jz clear_end |
mov esi,eax ; esi = current directory cluster |
sub eax,2 |
jb clear_end |
mov ecx,[SECTORS_PER_CLUSTER] |
imul eax,ecx |
add eax,[DATA_START] |
|
clear_new_sector: |
mov edi,eax ; edi = current directory sector |
mov ebx,deltree_buffer |
call hd_read |
cmp [hd_error],0 |
jne clear_error |
|
mov edx,512/32 ; count of dir entrys per sector = 16 |
|
clear_analyze: |
mov al,[ebx+11] ; file attribute |
and al,0xf |
cmp al,0xf |
je clear_long_filename |
|
cmp byte [ebx],'.' ; parent or current directory |
je clear_next_entry |
cmp byte [ebx],0xe5 ; deleted |
je clear_next_entry |
cmp byte [ebx],0 ; empty |
je clear_write_last |
;je clear_next_entry |
|
mov eax,[ebx+20-2] ; first cluster of entry |
mov ax,[ebx+26] |
and eax,[fatMASK] |
|
test byte [ebx+11],0x10 ; is it directory? |
jz clear_file ; no |
|
push eax ebx |
mov eax,edi |
mov ebx,deltree_buffer ; save buffer over recursive call |
call hd_write ; write directory sector to disk |
cmp [hd_error],0 |
jne clear_error |
|
pop ebx eax |
|
call clear_directory ; recursive call !!! |
jc clear_error ; exit if error found |
|
push eax ebx |
mov eax,edi |
mov ebx,deltree_buffer |
call hd_read ; read directory sector again |
cmp [hd_error],0 |
jne clear_error_1 |
|
pop ebx eax |
|
clear_file: |
call clear_cluster_chain |
cmp [hd_error],0 |
jne clear_error |
|
clear_long_filename: |
mov byte [ebx],0xe5 |
|
clear_next_entry: |
add ebx,32 ; position of next dir entry |
dec edx |
jnz clear_analyze |
|
mov eax,edi |
mov ebx,deltree_buffer |
call hd_write ; write directory sector to disk |
cmp [hd_error],0 |
jne clear_error |
|
inc eax ; next sector |
dec ecx |
jnz clear_new_sector |
|
mov eax,esi |
call get_FAT ; get next cluster |
cmp [hd_error],0 |
jne clear_error |
|
jmp clear_new_cluster ; clear it |
|
clear_write_last: |
mov eax,edi |
mov ebx,deltree_buffer |
call hd_write ; write directory sector to disk |
cmp [hd_error],0 |
jne clear_error |
|
clear_end: |
popad |
clc |
ret |
clear_error_1: |
add esp,8 |
clear_error: |
popad |
stc |
ret |
|
|
delete_entry_name: |
;----------------------------------------------------- |
; input : eax = directory sector |
; ebx = directory pointer in buffer |
; longname_sec = 2 previous directory sectors |
; output : ecx = first cluster |
; change : eax,ebx,edx |
;----------------------------------------------------- |
mov byte [ebx],0xe5 |
mov ecx,[ebx+20-2] ; first cluster of file |
mov cx,[ebx+26] ; 0 length files start cluster = 0 |
and ecx,[fatMASK] |
|
delete_empty: |
sub ebx,32 |
cmp ebx,buffer |
jnb delete_test_long |
|
mov ebx,buffer |
call hd_write ; write directory sector back |
cmp [hd_error],0 |
jne delete_name_end |
|
xor eax,eax |
xchg eax,[longname_sec2] |
xchg eax,[longname_sec1] |
test eax,eax ; is there previous directory sector? |
jz delete_name_end ; no |
|
mov ebx,buffer |
call hd_read ; read previous sector |
cmp [hd_error],0 |
jne delete_name_end |
|
mov ebx,buffer+0x1e0 ; start from last entry |
|
delete_test_long: |
mov dh,[ebx+11] ; file attribute |
and dh,0xf |
cmp dh,0xf |
jne delete_write_buffer |
|
cmp byte [ebx],0x40 ; end of long dir entry? |
mov byte [ebx],0xe5 |
jb delete_empty |
|
delete_write_buffer: |
mov ebx,buffer |
call hd_write ; write directory sector back |
|
delete_name_end: |
ret |
|
|
rename: |
;----------------------------------------------------------- |
; input : eax = source directory name |
; edx = source path |
; ebx = dest directory name |
; edi = dest path |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 5 - file not found |
; 8 - disk full |
; 10 - access denied |
;----------------------------------------------------------- |
cmp [fat_type],0 |
jnz fat_ok_for_rename |
mov eax,ERROR_UNKNOWN_FS |
ret |
|
fat_ok_for_rename: |
; call reserve_hd1 |
|
pushad |
|
mov ebx,edx ; source path |
call get_cluster_of_a_path |
jc rename_entry_not_found |
|
mov ebx,PUSHAD_EAX ; source directory name |
call analyze_directory |
jc rename_entry_not_found |
|
mov [sector_tmp],eax ; save source sector |
mov [entry_pos],ebx |
mov esi,ebx |
mov edi,dir_entry |
mov ecx,32/4 |
cld |
rep movsd ; save entry |
|
mov ebx,PUSHAD_EDI ; dest path |
call get_cluster_of_a_path |
jc rename_entry_not_found |
|
mov edx,eax ; save dest directory cluster |
mov ebx,PUSHAD_EBX ; dest directory name |
push [longname_sec1] |
push [longname_sec2] |
call analyze_directory ; check if entry already exist |
cmp [hd_error],0 |
jne rename_entry_already_exist_1 |
|
pop [longname_sec2] |
pop [longname_sec1] |
jnc rename_entry_already_exist |
|
mov eax,edx |
call analyze_directory_to_write |
jc rename_disk_full |
|
mov esi,dir_entry |
mov edi,ebx |
mov ecx,32/4 |
cld |
rep movsd ; copy entry |
mov esi,PUSHAD_EBX ; dest directory name |
mov edi,ebx |
mov ecx,11 |
rep movsb ; copy name |
|
mov ebx,buffer ; save the directory name,length,cluster |
call hd_write |
|
test byte [dir_entry+11],0x10 ; is it directory? |
jz rename_not_dir ; no |
mov eax,[dir_entry+20-2] ; FAT entry |
mov ax,[dir_entry+26] |
and eax,[fatMASK] |
call change_2dot_cluster |
cmp [hd_error],0 |
jne rename_entry_already_exist |
|
rename_not_dir: |
cmp [hd_error],0 |
jne rename_entry_already_exist |
mov eax,[sector_tmp] |
mov ebx,buffer |
call hd_read ; read source directory sector |
cmp [hd_error],0 |
jne rename_entry_already_exist |
|
mov ebx,[entry_pos] |
call delete_entry_name |
cmp [hd_error],0 |
jne rename_entry_already_exist |
|
popad |
call update_disk ; write all of cache and fat to hd |
cmp [hd_error],0 |
jne rename_entry_already_exist_2 |
mov [hd1_status],0 |
xor eax,eax |
ret |
|
rename_entry_not_found: |
cmp [hd_error],0 |
jne rename_entry_already_exist |
popad |
mov [hd1_status],0 |
mov eax,ERROR_FILE_NOT_FOUND |
ret |
|
rename_entry_already_exist_1: |
add esp,8 |
rename_entry_already_exist: |
popad |
rename_entry_already_exist_2: |
mov [hd1_status],0 |
mov eax,ERROR_ACCESS_DENIED |
ret |
|
rename_disk_full: |
cmp [hd_error],0 |
jne rename_entry_already_exist |
popad |
mov [hd1_status],0 |
mov eax,ERROR_DISK_FULL |
ret |
|
|
change_2dot_cluster: |
;----------------------------------------------------------- |
; input : eax = directory cluster |
; edx = value to save |
; change : eax,ebx,edx |
;----------------------------------------------------------- |
cmp eax,[LAST_CLUSTER] |
ja not_2dot ; too big cluster number, something is wrong |
sub eax,2 |
jb not_2dot |
|
imul eax,[SECTORS_PER_CLUSTER] |
add eax,[DATA_START] |
mov ebx,buffer |
call hd_read |
cmp [hd_error],0 |
jne not_2dot |
|
cmp dword [ebx+32],'.. ' |
jnz not_2dot |
|
cmp edx,[ROOT_CLUSTER] ; is rootdir cluster? |
jne not_2dot_root |
xor edx,edx ; yes. set it zero |
|
not_2dot_root: |
mov [ebx+32+26],dx ; 16 bits low of cluster |
shr edx,16 |
mov [ebx+32+20],dx ; 16 bits high of cluster (=0 fat16) |
call hd_write |
|
not_2dot: |
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 [fat_type],0 |
jnz 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 |
|
|
;************************************************************************** |
; |
; 0x600008 - first entry in cache list |
; |
; +0 - lba sector |
; +4 - state of cache sector |
; 0 = empty |
; 1 = used for read ( same as in hd ) |
; 2 = used for write ( differs from hd ) |
; |
; +65536 - cache entries |
; |
;************************************************************************** |
|
|
hd_read: |
;----------------------------------------------------------- |
; input : eax = block to read |
; ebx = destination |
;----------------------------------------------------------- |
push ecx esi edi ; scan cache |
|
mov ecx,cache_max ; entries in cache |
mov esi,0x600000+8 |
mov edi,1 |
|
hdreadcache: |
|
cmp dword [esi+4],0 ; empty |
je nohdcache |
|
cmp [esi],eax ; correct sector |
je yeshdcache |
|
nohdcache: |
|
add esi,8 |
inc edi |
dec ecx |
jnz hdreadcache |
|
call find_empty_slot ; ret in edi |
cmp [hd_error],0 |
jne return_01 |
|
push eax edx |
|
call wait_for_hd_idle |
cmp [hd_error],0 |
jne hd_read_error |
|
cli |
xor eax,eax |
mov edx,[hdbase] |
inc edx |
out dx,al ; ATAFeatures à ¥£¨áâà "®á®¡¥Â®á⥩" |
inc edx |
inc eax |
out dx,al ; ATASectorCount áç¥â稪 ᥪâ®à ®¢ |
inc edx |
mov eax,[esp+4] |
out dx,al ; ATASectorNumber à ¥£¨áâà ®¬¥à  á¥ªâ®à  |
shr eax,8 |
inc edx |
out dx,al ; ATACylinder ®¬¥à 樫¨Â¤à  (¬« ¤è¨© ¡ ©â) |
shr eax,8 |
inc edx |
out dx,al ; ®¬¥à 樫¨Â¤à  (áâ à 訩 ¡ ©â) |
shr eax,8 |
inc edx |
and al,1+2+4+8 |
add al,byte [hdid] |
add al,128+64+32 |
out dx,al ; ®¬¥à £®«®¢ª¨/®¬¥à ¤¨áª |
inc edx |
mov al,20h |
out dx,al ; ATACommand à ¥£¨áâà ª®¬ Â¤ |
sti |
|
call wait_for_sector_buffer |
|
cmp [hd_error],0 |
jne hd_read_error |
|
cli |
push edi |
shl edi,9 |
add edi,0x600000+65536 |
mov ecx,256 |
mov edx,[hdbase] |
cld |
rep insw |
pop edi |
sti |
|
pop edx eax |
blok_read_2: |
lea esi,[edi*8+0x600000] |
mov [esi],eax ; sector number |
mov dword [esi+4],1 ; hd read - mark as same as in hd |
|
yeshdcache: |
|
mov esi,edi |
shl esi,9 |
add esi,0x600000+65536 |
mov edi,ebx |
mov ecx,512/4 |
cld |
rep movsd ; move data |
return_01: |
pop edi esi ecx |
ret |
|
|
hd_write: |
;----------------------------------------------------------- |
; input : eax = block |
; ebx = pointer to memory |
;----------------------------------------------------------- |
push ecx esi edi |
|
; check if the cache already has the sector and overwrite it |
|
mov ecx,cache_max |
mov esi,0x600000+8 |
mov edi,1 |
|
hdwritecache: |
|
cmp dword [esi+4],0 ; if cache slot is empty |
je not_in_cache_write |
|
cmp [esi],eax ; if the slot has the sector |
je yes_in_cache_write |
|
not_in_cache_write: |
|
add esi,8 |
inc edi |
dec ecx |
jnz hdwritecache |
|
; sector not found in cache |
; write the block to a new location |
|
call find_empty_slot ; ret in edi |
cmp [hd_error],0 |
jne hd_write_access_denied |
|
lea esi,[edi*8+0x600000] |
mov [esi],eax ; sector number |
|
yes_in_cache_write: |
|
mov dword [esi+4],2 ; write - differs from hd |
|
shl edi,9 |
add edi,0x600000+65536 |
mov esi,ebx |
mov ecx,512/4 |
cld |
rep movsd ; move data |
hd_write_access_denied: |
pop edi esi ecx |
ret |
|
|
write_cache: |
;----------------------------------------------------------- |
; write all changed sectors to disk |
;----------------------------------------------------------- |
push eax ecx edx esi edi |
|
; write difference ( 2 ) from cache to hd |
|
mov ecx,cache_max |
mov esi,0x600000+8 |
mov edi,1 |
|
write_cache_more: |
|
cmp dword [esi+4],2 ; if cache slot is not different |
jne does_not_need_writing |
|
mov dword [esi+4],1 ; same as in hd |
mov eax,[esi] ; eax = sector to write |
|
cmp eax,[PARTITION_START] |
jb danger |
cmp eax,[PARTITION_END] |
ja danger |
|
call wait_for_hd_idle |
cmp [hd_error],0 |
jne hd_write_error |
|
cli |
xor eax,eax |
mov edx,[hdbase] |
inc edx |
out dx,al |
inc edx |
inc eax |
out dx,al |
inc edx |
mov eax,[esi] ; eax = sector to write |
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,byte [hdid] |
add al,128+64+32 |
out dx,al |
inc edx |
mov al,30h |
out dx,al |
sti |
|
call wait_for_sector_buffer |
|
cmp [hd_error],0 |
jne hd_write_error |
|
push ecx esi |
|
cli |
mov esi,edi |
shl esi,9 |
add esi,0x600000+65536 ; esi = from memory position |
mov ecx,256 |
mov edx,[hdbase] |
cld |
rep outsw |
sti |
|
pop esi ecx |
|
danger: |
does_not_need_writing: |
|
add esi,8 |
inc edi |
dec ecx |
jnz write_cache_more |
return_02: |
pop edi esi edx ecx eax |
ret |
|
|
find_empty_slot: |
;----------------------------------------------------------- |
; find empty or read slot, flush cache if next 10% is used by write |
; output : edi = cache slot |
;----------------------------------------------------------- |
push ecx esi |
|
search_again: |
|
mov ecx,cache_max*10/100 |
mov edi,[cache_search_start] |
|
search_for_empty: |
|
inc edi |
cmp edi,cache_max |
jbe inside_cache |
mov edi,1 |
|
inside_cache: |
|
cmp dword [edi*8+0x600000+4],2 ; get cache slot info |
jb found_slot ; it's empty or read |
dec ecx |
jnz search_for_empty |
|
call write_cache ; no empty slots found, write all |
cmp [hd_error],0 |
jne found_slot_access_denied |
|
jmp search_again ; and start again |
|
found_slot: |
|
mov [cache_search_start],edi |
found_slot_access_denied: |
pop esi ecx |
ret |
|
|
save_hd_wait_timeout: |
|
push eax |
mov eax,[timer_ticks];[0xfdf0] |
add eax,300 ; 3 sec timeout |
mov [hd_wait_timeout],eax |
pop eax |
ret |
|
|
check_hd_wait_timeout: |
|
push eax |
mov eax,[hd_wait_timeout] |
cmp [timer_ticks], eax ;[0xfdf0],eax |
jg hd_timeout_error |
pop eax |
mov [hd_error],0 |
ret |
|
iglobal |
hd_timeout_str db 'K : FS - HD timeout',13,10,0 |
hd_read_str db 'K : FS - HD read error',13,10,0 |
hd_write_str db 'K : FS - HD write error',13,10,0 |
hd_lba_str db 'K : FS - HD LBA error',13,10,0 |
endg |
|
hd_timeout_error: |
|
call clear_hd_cache |
call clear_application_table_status |
mov esi,hd_timeout_str |
call sys_msg_board_str |
; jmp $ |
mov [hd_error],1 |
pop eax |
ret |
|
hd_read_error: |
|
call clear_hd_cache |
call clear_application_table_status |
mov esi,hd_read_str |
call sys_msg_board_str |
pop edx eax |
jmp return_01 |
; jmp $ |
|
hd_write_error: |
|
call clear_hd_cache |
call clear_application_table_status |
mov esi,hd_write_str |
call sys_msg_board_str |
jmp return_02 |
; jmp $ |
|
hd_lba_error: |
call clear_hd_cache |
call clear_application_table_status |
mov esi,hd_lba_str |
call sys_msg_board_str |
jmp LBA_read_ret |
|
|
wait_for_hd_idle: |
|
push eax edx |
|
call save_hd_wait_timeout |
|
mov edx,[hdbase] |
add edx,0x7 |
|
wfhil1: |
|
call check_hd_wait_timeout |
cmp [hd_error],0 |
jne @f |
|
in al,dx |
test al,128 |
jnz wfhil1 |
|
@@: |
|
pop edx eax |
ret |
|
|
|
wait_for_sector_buffer: |
|
push eax edx |
|
mov edx,[hdbase] |
add edx,0x7 |
|
call save_hd_wait_timeout |
|
hdwait_sbuf: ; wait for sector buffer to be ready |
|
call check_hd_wait_timeout |
cmp [hd_error],0 |
jne @f |
|
in al,dx |
test al,8 |
jz hdwait_sbuf |
|
mov [hd_error],0 |
|
cmp [hd_setup],1 ; do not mark error for setup request |
je buf_wait_ok |
|
test al,1 ; previous command ended up with an error |
jz buf_wait_ok |
@@: |
mov [hd_error],1 |
|
buf_wait_ok: |
|
pop edx eax |
ret |
|
|
|
read_hd_file: |
;----------------------------------------------------------------- |
; |
; Converting old reading function for hd-application start. |
; |
; IN: |
; |
; eax - pointer to file (0 = read only first sector of drive: eg 'label') |
; ebx - file lenght |
; ecx - start 512 byte block number |
; edx - number of blocks to read |
; esi - pointer to return/work area (atleast 20 000 bytes) |
; |
; For new read function |
; |
; EAX (PAR0) pointer to file-name |
; ECX (PAR1) pointer to buffer |
; EBX (PAR2) vt file blocks to read |
; EDX (PAR3) pointer to path |
; ESI vt first 512 block to read |
; EDI if 0 - return root |
;-------------------------------------------------------------------------- |
|
push ecx esi edi |
mov esi,eax |
mov edi,startpath |
mov ecx,250 |
cld |
rep movsb |
pop edi esi ecx |
|
mov eax,startpath |
mov [eax+ebx-12],byte 0 |
|
push eax ebx ecx edx esi |
|
pop ecx ; pointer to buffer |
add ecx,1024 |
pop ebx ; number of blocks to read |
pop esi ; first block to read |
dec esi |
pop eax ; file length |
pop edx ; pointer to path |
|
mov edi,12 |
lea eax,[eax+edx-12+1] |
call file_read |
|
ret |
|
; \begin{diamond} |
hd_find_lfn: |
; in: esi->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 [fat_type], 32 |
jz .fat32 |
.loop: |
call fat_find_lfn |
jc .notfound |
cmp byte [esi], 0 |
jz .found |
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: |
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 [fat_type], 0 |
jnz @f |
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 |
|
.noaccess_3: |
add esp,4 |
.noaccess_1: |
add esp,4 |
.noaccess_4: |
add esp,4*5 |
jmp .noaccess_2 |
|
@@: |
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 |
cmp [hd_error],0 |
jne .noaccess_1 |
pop ebx |
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 |
cmp [hd_error],0 |
jne .noaccess_3 |
|
mov eax, ebx |
pop ebx |
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_4 |
|
jmp .new_cluster |
.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: |
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 [fat_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 ecx |
mov ecx, [eax+4] |
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 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 |
mov eax, [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 |
mov [f_del], 1 |
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_HdRewrite: |
cmp [fat_type], 0 |
jz fshrfs |
cmp byte [esi], 0 |
jz fshrad |
pushad |
xor ebp, ebp |
push esi |
@@: |
lodsb |
test al, al |
jz @f |
cmp al, '/' |
jnz @b |
lea ebp, [esi-1] |
jmp @b |
@@: |
pop esi |
test ebp, ebp |
jnz .noroot |
mov ebp, [ROOT_CLUSTER] |
cmp [fat_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 |
.noroot: |
; check existence |
mov byte [ebp], 0 |
call hd_find_lfn |
mov byte [ebp], '/' |
lea esi, [ebp+1] |
jnc @f |
mov eax, ERROR_FILE_NOT_FOUND |
.ret1: |
mov [esp+28], eax |
popad |
xor ebx, ebx |
ret |
@@: |
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; must not be directory |
test byte [edi+11], 10h |
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 |
mov [f_del], 1 |
@@: |
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 |
.doit: |
lea eax, [esp+8] |
call dword [eax+16] ; flush directory |
push ecx |
mov ecx, [esp+4+32+24] |
push ecx |
push edi |
mov esi, edx |
test ecx, ecx |
jz .done |
mov eax, 2 |
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: |
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 |
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 |
mov [f_del], 1 |
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 |
|
fs_HdGetFileInfo: |
cmp [fat_type], 0 |
jnz @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 [fat_type], 0 |
jnz @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_HdExecute - LFN variant for executing from harddisk |
; |
; esi points to hd filename (e.g. 'dir1/name') |
; ebp points to full filename (e.g. '/hd0/1/dir1/name') |
; dword [ebx] = flags |
; dword [ebx+4] = cmdline |
; |
; ret ebx,edx destroyed |
; eax > 0 - PID, < 0 - error |
; |
;-------------------------------------------------------------- |
fs_HdExecute: |
mov edx, [ebx] |
mov ebx, [ebx+4] |
test ebx, ebx |
jz @f |
add ebx, std_application_base_address |
@@: |
|
;---------------------------------------------------------------- |
; |
; fs_HdExecute.flags - second entry |
; |
; esi points to floppy filename (kernel address) |
; ebp points to full filename |
; edx flags |
; ebx cmdline (kernel address) |
; |
; ret eax > 0 - PID, < 0 - error |
; |
;-------------------------------------------------------------- |
|
.flags: |
cmp [fat_type], 0 |
jnz @f |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
cmp byte [esi], 0 |
jnz @f |
; cannot execute root! |
mov eax, -ERROR_ACCESS_DENIED |
ret |
@@: |
push edi |
call hd_find_lfn |
jnc .found |
pop edi |
mov eax, -ERROR_FILE_NOT_FOUND |
cmp [hd_error], 0 |
jz @f |
mov al, -11 |
@@: |
ret |
.found: |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
push 0 |
push eax |
push dword [edi+28] ; size |
push .DoRead |
call fs_execute |
add esp, 16 |
pop edi |
ret |
|
.DoRead: |
; read next block |
; in: eax->parameters, edi->buffer |
; out: eax = error code |
pushad |
cmp dword [eax], 0 ; file size |
jz .eof |
add eax, 4 |
call fat_get_sector |
mov ebx, edi |
call hd_read |
cmp [hd_error], 0 |
jnz .err |
mov eax, [esp+28] |
mov ecx, [eax] |
sub ecx, 512 |
jae @f |
lea edi, [edi+ecx+512] |
neg ecx |
push eax |
xor eax, eax |
rep stosb |
pop eax |
@@: |
mov [eax], ecx |
mov edx, [eax+8] |
inc edx |
cmp edx, [SECTORS_PER_CLUSTER] |
jb @f |
push eax |
mov eax, [eax+4] |
call get_FAT |
cmp [hd_error], 0 |
jnz .err |
mov ecx, eax |
pop eax |
mov [eax+4], ecx |
xor edx, edx |
@@: |
mov [eax+8], edx |
popad |
xor eax, eax |
ret |
.eof: |
popad |
mov eax, 6 |
ret |
.err: |
popad |
mov eax, 11 |
ret |
|
; \end{diamond} |