Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1 → Rev 2

/kernel/trunk/fs/fat12.inc
0,0 → 1,1084
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; FAT12.INC ;;
;; (C) 2005 Mario79, License: GPL ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
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,[0x3000]
shl eax,5
mov eax,[eax+0x3000+4]
mov [flp_status],eax
pop eax
sti
ret
 
floppy_free_space:
;---------------------------------------------
;
; returns free space in edi
;
;---------------------------------------------
push eax ebx ecx
call read_flp_fat
cmp [FDC_Status],0
jne fdc_status_error_2
mov eax,0x282000
xor edi,edi
mov ecx,2847 ;1448000/512
rdfs1_1:
mov ebx,[eax]
and ebx,4095
cmp ebx,0
jne rdfs2_1
add edi,512
rdfs2_1:
add eax,2
loop rdfs1_1
fdc_status_error_2:
pop ecx ebx eax
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
cmp esi,0 ; return ramdisk root
jne fr_noroot_1
cmp ebx,224/16
jbe fr_do_1
mov eax,5
mov ebx,0
mov [flp_status],0
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,0x8000
add esi,ebx
shl ecx,9
cld
rep movsb
mov eax,0 ; ok read
mov ebx,0
mov [flp_status],0
ret
fdc_status_error_1:
mov [flp_status],0
mov eax,10
mov ebx,-1
ret
 
fr_noroot_1:
sub esp,32
call expand_filename
frfloppy_1:
cmp ebx,0
jne frfl5_1
mov ebx,1
frfl5_1:
cmp ecx,0
jne 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,0xD000
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
cmp dl,0
jne l.21_1
dec dh
cmp dh,0
jne l.20_1
fdc_status_error_3:
mov eax,5 ; file not found ?
mov 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,0x282000
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
mov eax,0
mov [flp_status],0
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,0x8000
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,0x8000
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,0x8000
mov edi,0x282000
 
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,0x282000+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,0xD000+39
mov ecx,15
cld
rep cmpsb
je same_label
mov [root_read],0
mov [flp_fat],0
same_label:
mov esi,0xD000+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,0x8000
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,0x8000
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,0x282000
mov edi,0x8000
 
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,0x8000+0x1200 ;4274 bytes - all used FAT
jb fcnew2_1
 
mov esi,0x8000 ; duplicate fat chain
mov edi,0x8000+0x1200
mov ecx,0x1200/4
cld
rep movsd
 
popad
ret
 
 
floppy_filedelete:
;--------------------------------------------
;
; filedelete - sys floppy
; in:
; eax - filename 11 chars - for root directory
; edi pointer to path /fd/1/...... - for all files in nested directories
;
; out:
; eax - 0 = successful, 1 = file not found, 10 = access denied
;
;--------------------------------------------
mov [path_pointer_flp],edi
mov [save_flag],0
mov ebp,1 ; file not found as default
filedelete_newtry_1:
sub esp,32
call expand_filename
push eax ebx ecx edx esi edi
call read_flp_fat
cmp [FDC_Status],0
jne frnoreadd_1
mov [FDD_Track],0 ; Öèëèíäð
mov [FDD_Head],1 ; Ñòîðîíà
mov [FDD_Sector],2 ; Ñåêòîð
call SeekTrack
mov dh,14
l.20_2:
call ReadSectWithRetr
cmp [FDC_Status],0
jne fdc_status_error_4
mov dl,16
mov edi,0xD000
inc [FDD_Sector]
l.21_2:
mov esi,eax ;Name of file we want
mov ecx,11
cld
rep cmpsb ;Found the file?
je fifoundd_1 ;Yes
add ecx,21
add edi, ecx ;Advance to next entry
dec dl
cmp dl,0
jne l.21_2
dec dh
cmp dh,0
jne l.20_2
jmp frnoreadd_1
 
fdc_status_error_4:
pop edi esi edx ecx ebx eax
add esp,32
jmp fdc_status_error_1
 
fifoundd_1:
mov eax,[path_pointer_flp]
cmp [eax+36],byte 0
je fifoundd_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 frnoreadd_1_1
mov edi,ebx
add edi,11
jmp fifoundd_2_1
fifoundd_2:
dec [FDD_Sector]
fifoundd_2_1:
mov [edi-11],byte 0xE5 ;mark filename deleted
add edi,0xf
mov eax,[edi]
and eax,65535
mov edi,eax ;edi = cluster
frnewd_1:
shl edi,1 ;find next cluster from FAT
add edi,0x282000
mov eax,[edi]
mov [edi],word 0x0 ;clear fat chain cluster
and eax,4095
mov edi,eax
cmp edi,dword 4095 ;last cluster ?
jz frnoreadd2_1
jmp frnewd_1
 
frnoreadd2_1:
call WriteSectWithRetr
cmp [FDC_Status],0
jne fdc_status_error_4
call save_flp_fat
cmp [FDC_Status],0
jne fdc_status_error_4
; pop edi esi edx ecx ebx eax
; add esp,32
mov ebp,0 ; file found
; jmp filedelete_newtry_1
jmp frnoreadd_1
 
frnoreadd_1_1:
cmp [FDC_Status],0
jne fdc_status_error_4
frnoreadd_1:
pop edi esi edx ecx ebx eax
add esp,32
mov eax,ebp
ret
 
floppy_filesave:
;----------------------------------------------------------
;
; filesave - sys floppy
;
; eax ; pointer to file name 11 chars - for root directory
; ebx ; buffer
; ecx ; count to write in bytes
; edx ; 0 create new , 1 append
; edi pointer to path /fd/1/...... - for all files in nested directories
;
; output : eax = 0 - ok
; 5 - file not found / directory not found
; 8 - disk full
; 10 - access denied
;-----------------------------------------------------------
mov [path_pointer_flp],edi
sub esp,32
call expand_filename
cmp edx,0
jnz fsdel_1
pusha
call floppy_filedelete
cmp [FDC_Status],0
jne fdc_status_error_6
popa
mov [save_flag],1
fsdel_1:
call floppy_free_space
cmp [FDC_Status],0
jne fdc_status_error_6
cmp ecx,edi
jb rd_do_save_1
add esp,32
mov eax,8 ; not enough free space
mov [flp_status],0
ret
 
fdc_status_error_6:
popa
add esp,32
jmp fdc_status_error_1
rd_do_save_1:
push eax ebx ecx edx esi edi
call read_flp_fat
cmp [FDC_Status],0
jne fdc_status_error_7
push eax
mov eax,[path_pointer_flp]
cmp [eax+36],byte 0
jne fifoundds_2
pop eax
mov [save_root_flag],1
call read_flp_root
cmp [FDC_Status],0
jne fdc_status_error_7
mov edi,0x8000 ;Point at directory
mov edx,224 +1
; find an empty spot for filename in the root dir
l20ds_1:
sub edx,1
cmp edx,0
jnz l21ds_1
jmp frnoreadds_1
l21ds_1:
cmp [edi],byte 0xE5
jz fifoundds_1
cmp [edi],byte 0x0
jz fifoundds_1
add edi,32 ; Advance to next entry
jmp l20ds_1
 
fifoundds_2:
pop eax
mov [save_root_flag],0
mov [FDD_Track],0 ; Öèëèíäð
mov [FDD_Head],1 ; Ñòîðîíà
mov [FDD_Sector],2 ; Ñåêòîð
call SeekTrack
mov dh,14
l.20_3:
call ReadSectWithRetr
cmp [FDC_Status],0
jne fdc_status_error_7
mov dl,16
mov edi,0xD000
inc [FDD_Sector]
l.21_3:
mov esi,eax ;Name of file we want
mov ecx,11
cld
rep cmpsb ;Found the file?
je fifoundds_3 ;Yes
add ecx,21
add edi, ecx ;Advance to next entry
dec dl
cmp dl,0
jne l.21_3
dec dh
cmp dh,0
jne l.20_3
fdc_status_error_8:
pop edi esi edx ecx ebx eax
mov eax,5 ; file not found ?
mov ebx,-1
add esp,32
mov [flp_status],0
ret
 
fifoundds_3:
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_7_1
found_directory_for_writing_flp:
call analyze_directory_to_write_flp
jc fdc_status_error_7_1
mov edi,ebx
fifoundds_1:
push edi ; move the filename to root dir
mov esi,[esp+4+20]
cmp [save_root_flag],0
jne fifoundds_4
mov esi,[pointer_file_name_flp]
fifoundds_4:
mov ecx,11
cld
rep movsb
pop edi
mov edx,edi
add edx,11+0xf ; edx <- cluster save position
mov ebx,[esp+12] ; save file size
mov [edi+28],ebx
mov [edi+11],byte 0x20 ; attribute
call get_date_for_file ; from FAT32.INC
mov [edi+24],ax ; date
mov [edi+18],ax ; date
call get_time_for_file ; from FAT32.INC
mov [edi+22],ax ; time
xor ax,ax
mov [edi+20],ax
mov ebx,1 ; first cluster
cmp [save_root_flag],0
jne frnewds_1
call frnewds_2
pusha
call WriteSectWithRetr
popa
cmp [FDC_Status],0
jne fdc_status_error_7
jmp frnewds_3
 
frnewds_1:
call frnewds_2
frnewds_3:
pusha ; move save to floppy cluster
add ebx,31
mov eax,ebx
mov esi,[esp+32+16]
call take_data_from_application_1
call save_chs_sector
cmp [FDC_Status],0
jne fdc_status_error_7
popa
mov eax,[esp+12]
cmp eax,512
jb flnsa_1
sub eax,512
mov [esp+12],eax
mov eax,[esp+16]
add eax,512
mov [esp+16],eax
jmp frnewds_1
 
frnewds_2:
add ebx,1
mov edi,ebx ; find free cluster in FAT
shl edi,1
add edi,0x282000
mov eax,[edi]
and eax,4095
cmp eax,0x0
jnz frnewds_2
mov [edx],bx ; save next cluster pos. to prev cl.
mov edx,edi ; next save pos abs mem add
ret
 
flnsa_1:
mov [edi],word 4095 ; mark end of file - last cluster
cmp [save_root_flag],1
jne flnsa_2
call save_flp_root
cmp [FDC_Status],0
jne fdc_status_error_7
flnsa_2:
call save_flp_fat
cmp [FDC_Status],0
jne fdc_status_error_7
frnoreadds_1:
pop edi esi edx ecx ebx eax
add esp,32
mov eax,0
mov [flp_status],0
ret
 
fdc_status_error_7_1:
cmp [FDC_Status],0
je fdc_status_error_8
fdc_status_error_7:
pop edi esi edx ecx ebx eax
add esp,32
jmp fdc_status_error_1
 
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
cmp edx,0
je 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,0xD000
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,0x282000
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
analyze_directory_to_write_flp:
;--------------------------------
; input : EAX = first cluster of the directory
; output : IF CARRY=0 EAX = sector where the file is found
; EBX = pointer in buffer
; [buffer .. buffer+511]
; ECX,EDX,EDI,EDI not changed
; IF CARRY=1
;--------------------------------
push ecx
push edx
push esi
adr561:
mov [clust_tmp_flp],eax
add eax,31
pusha
call read_chs_sector
popa
cmp [FDC_Status],0
jne error_found_file_analyze1
 
mov ecx,512/32
mov ebx,0xD000
adr1_analyze1:
cmp byte [ebx],0x00
je found_file_analyze1
cmp byte [ebx],0xe5
je found_file_analyze1
avanti:
add ebx,32
loop adr1_analyze1
mov eax,[clust_tmp_flp]
shl eax,1 ;find next cluster from FAT
add eax,0x282000
mov eax,[eax]
and eax,4095
cmp eax,0x0ff8
jb adr561
call get_free_FAT ;this block of code add a new cluster
;for the directory because the directory
;is full
 
mov [edi],word 0x0fff
mov eax,[clust_tmp_flp]
shl eax,1 ;find next cluster from FAT
add eax,0x282000
sub edi,0x282000
mov [eax],di
 
pusha
mov ecx,512/4
xor eax,eax
mov edi,0xD000
cld
rep stosd
popa
 
mov eax,edi
add eax,31
pusha
call save_chs_sector
popa
cmp [FDC_Status],0
jne error_found_file_analyze1
mov ebx,0xD000
 
found_file_analyze1:
pop esi
pop edx
pop ecx
clc ;file found
ret
 
error_found_file_analyze1:
pop esi
pop edx
pop ecx
stc
ret
get_free_FAT_flp:
;------------------------------------------
; input : EAX = # cluster for start the searching
; output : EAX = # first cluster found free
;-------------------------------------------
push ebx
mov ebx,1
check_new_flp:
add ebx,1
mov edi,ebx ; find free cluster in FAT
shl edi,1
add edi,0x282000
mov eax,[edi]
and eax,4095
cmp eax,0x0
jnz check_new_flp
 
pop ebx
ret
/kernel/trunk/fs/fat32.inc
0,0 → 1,2827
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; FAT32.INC ;;
;; ;;
;; FAT16/32 functions for MenuetOS ;;
;; ;;
;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;; 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_DISK_BASE equ 1
ERROR_UNSUPPORTED_FS equ 2
ERROR_UNKNOWN_FS equ 3
ERROR_PARTITION equ 4
ERROR_FILE_NOT_FOUND equ 5
ERROR_END_OF_FILE equ 6
ERROR_MEMORY_POINTER equ 7
ERROR_DISK_FULL equ 8
ERROR_FAT_TABLE equ 9
ERROR_ACCESS_DENIED equ 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]
 
align 4
;******************************************************
; Please do not change this place - variables in text
; Mario79
; START place
;******************************************************
PARTITION_START dd 0x3f
PARTITION_END dd 0
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
 
fat_type db 0 ; 0=none, 16=fat16, 32=fat32
;***************************************************************************
; End place
; Mario79
;***************************************************************************
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
 
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
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
 
 
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+4]
mov [hd1_status],eax
pop eax
sti
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
 
; Partition chain used:
; MBR ; PARTITION2 ; PARTITION3 ; PARTITION4
;==========================================================
; fat16/32 +-- fat16/32 +-- fat16/32 +-- fat16/32 +--
; extended --+ extended --+ extended --+ extended --+
; 0 0 0 0
; 0 0 0 0
; Notes:
; - extended partition need to be in second entry on table
; - it will skip over removed partitions
 
set_FAT32_variables:
mov [0xfe10],dword 0 ; entries in hd cache
mov [problem_partition],0
call reserve_hd1
call clear_hd_cache
 
cmp dword [hdpos],0
je problem_hd
 
pushad
xor ecx,ecx ; partition count
mov edx,-1 ; flag for partition
xor eax,eax ; read MBR
xor ebp,ebp ; extended partition start
 
new_partition:
test ebp,ebp ; is there extended partition?
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 word [ebx+0x1fe],0xaa55 ; is it valid boot sector?
jnz end_partition_chain
cmp dword [ebx+0x1be+0xc],0 ; skip over empty partition
jz next_partition
 
push eax ecx
mov edi,partition_types
mov ecx,partition_types_end-partition_types
mov al,[ebx+0x1be+4] ; get partition type
cld
repne scasb ; is partition type ok?
pop ecx eax
jnz next_partition ; no. skip over
 
inc ecx
cmp ecx,[fat32part] ; is it wanted partition?
jnz next_partition ; no
 
mov edx,eax ; start sector
add edx,[ebx+0x1be+8] ; add relative start
 
next_partition:
push ecx
mov edi,extended_types
mov ecx,extended_types_end-extended_types
mov al,[ebx+0x1be+4+16] ; get second partition type
cld
repne scasb ; is it extended partition?
pop ecx
jnz end_partition_chain ; no. end chain
 
mov eax,[ebx+0x1be+8+16] ; get start of extended partition
test eax,eax ; is there extended partition?
jnz new_partition ; 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_fat_dec_count: ; bootsector is missing or another problem
dec [partition_count] ; remove it from partition_count
 
problem_partition_or_fat:
popad
 
problem_hd:
mov [fat_type],0
mov [hd1_status],0 ; free
mov [problem_partition],1
ret
 
hd_and_partition_ok:
mov eax,edx
mov [PARTITION_START],eax
 
mov [hd_setup],1
mov ebx,buffer
call hd_read ; read boot sector of partition
mov [hd_setup],0
 
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
mov [SECTORS_PER_CLUSTER],eax
 
movzx ecx,word [ebx+0xb] ; bytes per sector
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
 
; 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
 
popad
 
mov [fatRESERVED],0x0FFFFFF6
mov [fatBAD],0x0FFFFFF7
mov [fatEND],0x0FFFFFF8
mov [fatMASK],0x0FFFFFFF
mov [fat_type],32 ; Fat32
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 [fat_type],16 ; Fat16
mov [hd1_status],0 ; free
ret
 
 
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
 
sfc_no_change:
mov [fat_in_cache],eax ; save fat sector
call hd_read
 
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
 
gfc_no_change:
mov [fat_in_cache],eax
call hd_read
 
gfc_in_cache:
mov eax,[ebx+esi]
and eax,[fatMASK]
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
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:
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
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
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 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
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 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
 
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
mov [f_del],0
 
mov ecx,-1 ; remove 1 cluster from free disk space
call add_disk_free_space
 
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
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:
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
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
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
 
make_dir_path_not_found:
popad
call update_disk ; write all of cache and fat to hd
mov [hd1_status],0
mov eax,ERROR_FILE_NOT_FOUND
ret
 
make_dir_disk_full:
popad
call update_disk ; write all of cache and fat to hd
mov [hd1_status],0
mov eax,ERROR_DISK_FULL
ret
 
make_dir_already_exist:
mov eax,[cluster] ; directory cluster
xor edx,edx ; free
mov [f_del],1
call set_FAT
mov [f_del],0
 
popad
call update_disk ; write all of cache and fat to hd
mov [hd1_status],0
mov eax,ERROR_ACCESS_DENIED
ret
 
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
pop eax
 
mov ebx,PUSHAD_EAX ; dir name
push eax
call analyze_directory ; check if directory already exist
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
 
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
dec edx
jnz dir_set_empty_directory
 
mov ecx,-1 ; remove 1 cluster from free disk space
call add_disk_free_space
 
popad
call update_disk ; write all of cache and fat to hd
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
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 dword [ebx+0x1fc],0xaa550000 ; check sector id
jne add_not_fs
 
add [ebx+0x1e8],ecx
call hd_write
 
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
 
push eax ; save first cluster
mov eax,[sector_tmp]
mov ebx,buffer
call hd_write ; write new file entry back to disk
pop eax
 
append_remove_free:
mov ecx,-1 ; remove 1 cluster from free disk space
call add_disk_free_space ; Note: uses buffer
 
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:
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
 
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 [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 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
mov edx,eax
mov eax,[cluster]
mov [f_del],1
call set_FAT ; update previous cluster
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:
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
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
 
sub ecx,PUSHAD_ESI ; start position
mov PUSHAD_EBX,ecx ; bytes written
popad
call update_disk ; write all of cache and fat to hd
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:
popad
mov [hd1_status],0
xor ebx,ebx
mov eax,ERROR_FILE_NOT_FOUND
ret
 
append_access:
popad
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
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
jmp truncate_new_cluster
 
truncate_pos_found:
mov edx,[fatEND] ; new end for cluster chain
mov [f_del],1
call set_FAT
mov [f_del],0
mov eax,edx ; clear rest of chain
 
truncate_clear_chain:
call clear_cluster_chain
 
truncate_eof:
popad
call update_disk ; write all of cache and fat to hd
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
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
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
 
exit_writing_with_error:
popad
call update_disk ; write all of cache and fat to hd
mov [hd1_status],0
mov eax,ERROR_FILE_NOT_FOUND
ret
 
exit_writing_disk_full_clear:
mov eax,[sector_tmp]
mov ebx,buffer
call hd_read ; read directory sector
mov edx,[entry_pos]
mov byte [edx],0xe5 ; mark as deleted
call hd_write
mov eax,[edx+20-2] ; FAT entry
mov ax,[edx+26]
and eax,[fatMASK]
call clear_cluster_chain
 
exit_writing_disk_full:
popad
call update_disk ; write all of cache and fat to hd
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
 
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
 
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
 
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
dec ecx ; update cluster count
jmp hd_new_block_write
 
file_saved_OK:
 
mov edx,[fatEND] ; new end for cluster chain
call set_FAT
dec ecx ; update cluster count
 
call add_disk_free_space ; remove clusters from free disk space
 
popad
call update_disk ; write all of cache and fat to hd
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
; ebx = size of file/directory
;--------------------------------------------------------------------------
cmp [fat_type],0
jnz fat_ok_for_reading
xor ebx,ebx
mov eax,ERROR_UNKNOWN_FS
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
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
 
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 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:
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:
popad
mov [hd1_status],0
xor ebx,ebx
mov eax,ERROR_FILE_NOT_FOUND
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
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
pop ebx
 
delete_notdir:
call delete_entry_name
mov eax,ecx ; first cluster of file
call clear_cluster_chain
popad
xor eax,eax
ret
 
delete_no_access:
popad
mov eax,ERROR_ACCESS_DENIED
ret
 
file_to_delete_not_found:
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
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
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
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
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
pop ebx eax
 
clear_file:
call clear_cluster_chain
 
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
 
inc eax ; next sector
dec ecx
jnz clear_new_sector
 
mov eax,esi
call get_FAT ; get next cluster
jmp clear_new_cluster ; clear it
 
clear_write_last:
mov eax,edi
mov ebx,deltree_buffer
call hd_write ; write directory sector to disk
 
clear_end:
popad
clc
ret
 
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
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
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
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
 
rename_not_dir:
mov eax,[sector_tmp]
mov ebx,buffer
call hd_read ; read source directory sector
 
mov ebx,[entry_pos]
call delete_entry_name
 
popad
call update_disk ; write all of cache and fat to hd
mov [hd1_status],0
xor eax,eax
ret
 
rename_entry_not_found:
popad
mov [hd1_status],0
mov eax,ERROR_FILE_NOT_FOUND
ret
 
rename_entry_already_exist:
popad
mov [hd1_status],0
mov eax,ERROR_ACCESS_DENIED
ret
 
rename_disk_full:
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 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_filesize:
;-----------------------------------------------------------
; input : eax = file name
; edx = path
; edi = if 0 - read rootdir else normal dir/file size
; output : eax = 0 - ok
; 3 - unknown FS
; 5 - file not found
; ebx = file size
;-----------------------------------------------------------
cmp [fat_type],0
jnz get_filesize_fat_ok
xor ebx,ebx
mov eax,ERROR_UNKNOWN_FS
ret
 
get_filesize_fat_ok:
; call reserve_hd1
 
pushad
xor eax,eax
test edi,edi ; is read rootdir?
je get_filesize_dirsize ; yes
 
get_filesize_no_root:
mov ebx,edx
call get_cluster_of_a_path
jc get_filesize_not_found
 
mov ebx,PUSHAD_EAX ; file name
call analyze_directory
jc get_filesize_not_found
 
mov eax,[ebx+28] ; file size
test byte [ebx+11],0x10 ; is it directory?
jz get_filesize_set_size ; no
 
mov eax,[ebx+20-2] ; FAT entry
mov ax,[ebx+26]
and eax,[fatMASK]
 
get_filesize_dirsize:
call get_dir_size
 
get_filesize_set_size:
mov PUSHAD_EBX,eax
popad
mov [hd1_status],0
xor eax,eax
ret
 
get_filesize_not_found:
popad
mov [hd1_status],0
xor ebx,ebx
mov eax,ERROR_FILE_NOT_FOUND
ret
 
 
get_fileattr:
;-----------------------------------------------------------
; input : eax = file name
; edx = path
; output : eax = 0 - ok
; 3 - unknown FS
; 5 - file not found
; ebx = file attribute
;-----------------------------------------------------------
cmp [fat_type],0
jnz get_fileattr_fat_ok
xor ebx,ebx
mov eax,ERROR_UNKNOWN_FS
ret
 
get_fileattr_fat_ok:
; call reserve_hd1
 
pushad
mov ebx,edx
call get_cluster_of_a_path
jc get_fileattr_not_found
 
mov ebx,PUSHAD_EAX ; file name
call analyze_directory
jc get_fileattr_not_found
 
movzx eax,byte [ebx+11] ; file attribute
mov PUSHAD_EBX,eax
popad
mov [hd1_status],0
xor eax,eax
ret
 
get_fileattr_not_found:
popad
mov [hd1_status],0
xor ebx,ebx
mov eax,ERROR_FILE_NOT_FOUND
ret
 
 
get_filedate:
;-----------------------------------------------------------
; input : eax = file name
; edx = path
; output : eax = 0 - ok
; 3 - unknown FS
; 5 - file not found
; ebx = file date/time
; bits 31..25 = year-1980
; bits 24..21 = month
; bits 20..16 = day
; bits 15..11 = hour
; bits 10..5 = minute
; bits 4..0 = second/2
;-----------------------------------------------------------
cmp [fat_type],0
jnz get_filedate_fat_ok
xor ebx,ebx
mov eax,ERROR_UNKNOWN_FS
ret
 
get_filedate_fat_ok:
; call reserve_hd1
 
pushad
mov ebx,edx
call get_cluster_of_a_path
jc get_filedate_not_found
 
mov ebx,PUSHAD_EAX ; file name
call analyze_directory
jc get_filedate_not_found
 
mov eax,[ebx+22] ; file date/time
mov PUSHAD_EBX,eax
popad
mov [hd1_status],0
xor eax,eax
ret
 
get_filedate_not_found:
popad
mov [hd1_status],0
xor ebx,ebx
mov eax,ERROR_FILE_NOT_FOUND
ret
 
 
get_hd_info:
;-----------------------------------------------------------
; output : eax = 0 - ok
; 3 - unknown FS
; 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
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
 
 
update_disk:
;-----------------------------------------------------------
; write changed fat and cache to disk
;-----------------------------------------------------------
cmp [fat_change],0 ; is fat changed?
je upd_no_change
 
call write_fat_sector
 
upd_no_change:
 
call write_cache
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
 
call wait_for_hd_idle
push eax edx
 
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
; blok_read_2:
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
 
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
 
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
 
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
 
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
jmp search_again ; and start again
 
found_slot:
 
mov [cache_search_start],edi
 
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
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
endg
 
hd_timeout_error:
 
call clear_hd_cache
call clear_application_table_status
mov esi,hd_timeout_str
call sys_msg_board_str
jmp $
 
 
hd_read_error:
 
call clear_hd_cache
call clear_application_table_status
mov esi,hd_read_str
call sys_msg_board_str
jmp $
 
hd_write_error:
 
call clear_hd_cache
call clear_application_table_status
mov esi,hd_write_str
call sys_msg_board_str
jmp $
 
 
 
 
wait_for_hd_idle:
 
push eax edx
 
call save_hd_wait_timeout
 
mov edx,[hdbase]
add edx,0x7
 
wfhil1:
 
call check_hd_wait_timeout
 
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
 
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
 
/kernel/trunk/fs/fs.inc
0,0 → 1,1095
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; System service for filesystem call ;;
;; (C) 2004 Ville Turjanmaa, License: GPL ;;
;; ;;
;; 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 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
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 /HardDisk/First 30
; eax = 1 ; write file /RamDisk/First 33 /HardDisk/First 56
; eax = 2 ; delete file /RamDisk/First 32 /HardDisk/First 57
; eax = 3 ; append to a file /RamDisk/First ?? /HardDisk/First ??
; eax = 4 ; makedir
; eax = 5 ; rename file/directory
; eax = 8 ; lba read
; eax = 12 ; get_filesize
; eax = 13 ; get_fileattr
; eax = 14 ; get_filedate
; eax = 15 ; get_disk_info
; eax = 16 ; start application
;
; OUT:
;
; eax = 0 : read ok
; eax = 1 : no fd base and/or partition defined
; eax = 2 : yet unsupported 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
;
; ebx = size
 
; Extract parameters
 
mov edi,[0x3010]
add eax,[edi+0x10] ; abs start of info block
 
cmp dword [eax+0],12 ; Get file size
je fs_read
cmp dword [eax+0],13 ; Get file attribute
je fs_read
cmp dword [eax+0],14 ; Get file date/time
je fs_read
cmp dword [eax+0],15 ; GET_DISK_INFO
je fs_info
cmp dword [eax+0],16 ; RUN - dont care about read&write blocks
je fs_read
cmp dword [eax+0],5 ; RENAME - dont care about read&write blocks
je fs_read
cmp dword [eax+0],4 ; MAKEDIR - dont care about read&write blocks
je fs_read
cmp dword [eax+0],2 ; DELETE - dont care about read&write blocks
je fs_read
 
cmp dword [0x3000],1 ; no memory checks for kernel requests
jz no_checks_for_kernel
;iglobal
; buffer_failed db 'Buffer check failed',13,10,0
;endg
mov edx,eax
cmp dword [eax+0],1
jz .check_for_write_op
cmp dword [eax+0],3
jnz .usual_check
.check_for_write_op:
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 '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
jmp area_in_app_mem
; mov ebx,[0x3000] ; pointer in application memory ?
; shl ebx,8
; mov ebx,[ebx+0x80000+0x8c]
 
; mov ebp,ebx ; save for checking at stack save
; sub ebp,[eax+12]
; shr ebp,9
 
; sub ebx,512 ; need atleast one block
 
; cmp ebx,[eax+12]
; ja area_in_app_mem
; mov eax,7
; mov dword [esp+36],7
; ret
area_in_app_mem:
mov eax,edx
no_checks_for_kernel:
 
 
cmp dword [eax+0],3 ; APPEND - allow write 0 bytes (truncate)
je fs_read
cmp dword [eax+8],0 ; read or write 0 blocks/bytes ?
jne fs_read
mov dword [esp+36],0
ret
fs_read:
 
mov ebx,[eax+20] ; program wants root directory ?
test bl,bl
je fs_getroot
test bh,bh
jne fs_noroot
fs_getroot:
mov edx,[edi+0x10]
mov esi,dir0
mov edi,[eax+12]
add edi,edx
mov ecx,11
cld
rep movsb
mov eax,0x10
stosb
add edi,32-11-1
mov ecx,11
rep movsb
stosb
mov dword [esp+36],0 ; ok read
mov dword [esp+24],32*2 ; size of root
ret
 
fs_info: ;start of code - Mihasik
mov edi,eax
push edi
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:
 
mov ebx,[eax+0]
push ebx ; read/write/delete/.../makedir/rename/lba/run
mov ebx,[eax+4]
push ebx ; 512 block number to read
mov ebx,[eax+8]
 
; cmp dword [eax+0],0 ; if read, check that the data stays at
; jne ret_size_fine ; application memory
; cmp ebx,ebp
; jbe ret_size_fine
; mov ebx,ebp
; ret_size_fine:
 
push ebx ; bytes to write/append or 512 blocks to read
mov ebx,[eax+12]
add ebx,[edi+0x10]
push ebx ; abs start of return/save area
 
lea esi,[eax+20] ; abs start of dir + filename
mov edi,[edi+0x10] ; abs start of work area
add edi,[eax+16]
 
call expand_pathz
 
push edi ; dir start
push ebx ; name of file start
 
mov ebx,[dir0+11] ; /RAMDISK
mov eax,[edi+1]
cmp eax,'RD '
je fs_yesramdisk
cmp eax,ebx
jne fs_noramdisk
 
fs_yesramdisk:
 
cmp byte [edi+1+11],0
je fs_give_dir1
 
mov ebx,[dir1] ; /FIRST
mov eax,[edi+1+12]
cmp eax,'1 '
je fs_yesramdisk_first
cmp eax,ebx
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:
 
cmp dword [esp+20],1 ; WRITE
jne fs_noramdisk_write
 
mov eax,[esp+4] ; fname
add eax,2*12+1
mov ebx,[esp+8] ; buffer
mov ecx,[esp+12] ; count to write
mov edx,0 ; create new
call filesave
 
; eax=0 ok - eax=1 not enough free space
 
jmp file_system_return
 
fs_noramdisk_write:
 
cmp dword [esp+20],16 ; START APPLICATION
jne fs_noramdisk_start_application
 
mov eax,[esp+4] ; fname
add eax,2*12+1
 
xor ebx,ebx ; parameters to pass
cmp dword [esp+12],0
je no_fl_start_param
mov ebx,[0x3010]
mov ebx,[ebx+0x10]
add ebx,[esp+12]
no_fl_start_param:
 
call start_application_fl
 
jmp file_system_return
 
fs_noramdisk_start_application: ;there's new code - Mihasik
cmp dword [esp+20],2 ;DELETE
jne fs_noramdisk_delete
mov eax,[esp+4] ; fname
add eax,2*12+1
call filedelete
jmp file_system_return
 
fs_noramdisk_delete:
cmp dword [esp+20],12 ;GET TIME,DATE,SIZE AND ATTRS
jb fs_noramdisk_getinfo
cmp dword [esp+20],14
ja fs_noramdisk_getinfo
mov eax,[esp+4] ; fname
add eax,2*12+1
mov ebx,[esp+20]
mov ecx,[esp+0]
sub ecx,eax
add ecx,12+1 ; file name length
call rd_getfileinfo
jmp file_system_return
fs_noramdisk_getinfo: ;End of code - Mihasik
 
fs_noramdisk:
;********************************************************************
mov ebx,[dir0+22] ; /FLOPPYDISK
mov eax,[edi+1]
cmp eax,'FD '
je fs_yesflpdisk
cmp eax,ebx
jne fs_noflpdisk
 
fs_yesflpdisk:
call reserve_flp
 
cmp byte [edi+1+11],0
je fs_give_dir1
 
mov ebx,[dir1] ; /FIRST
mov eax,[edi+1+12]
cmp eax,'1 '
je fs_yesflpdisk_first
cmp eax,ebx
je fs_yesflpdisk_first
mov ebx,[dir1+11] ; /SECOND
cmp eax,'2 '
je fs_yesflpdisk_second
cmp eax,ebx
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:
 
cmp dword [esp+20],1 ; WRITE
jne fs_noflpdisk_write
 
mov eax,[esp+4] ; fname
add eax,2*12+1
mov ebx,[esp+8] ; buffer
mov ecx,[esp+12] ; count to write
mov edx,0 ; create new
call floppy_filesave
 
; eax=0 ok - eax=1 not enough free space
 
jmp file_system_return
 
fs_noflpdisk_write:
 
cmp dword [esp+20],2 ; DELETE
jne fs_noflpdisk_delete
 
mov eax,[esp+4] ; fname
add eax,2*12+1
call floppy_filedelete
mov [flp_status],0
jmp file_system_return
 
fs_noflpdisk_delete:
cmp dword [esp+20],16 ; START APPLICATION
jne fs_noflpdisk_start_application
 
mov eax,[esp+4] ; fname
add eax,2*12+1
 
xor ebx,ebx ; parameters to pass
cmp dword [esp+12],0
je no_flp_start_param
mov ebx,[0x3010]
mov ebx,[ebx+0x10]
add ebx,[esp+12]
 
no_flp_start_param:
 
call start_application_floppy
 
jmp file_system_return
 
fs_noflpdisk_start_application:
 
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 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 [0xfe10],dword 0 ; entries in hd cache
mov ecx,[hdpos]
xor eax,eax
mov edx,0x40002
search_partition_array:
mov bl,[edx]
movzx ebx,bl
add eax,ebx
inc edx
loop search_partition_array
sub eax,ebx
add eax,[fat32part]
dec eax
xor edx,edx
imul eax,100
add eax,0x4000a
mov [transfer_adress],eax
call partition_data_transfer_1
ret
 
old_path_harddisk:
mov ebx,[dir0] ; /HARDDISK
mov eax,[edi+1]
cmp eax,'HD '
je fs_yesharddisk
cmp eax,ebx
jne fs_noharddisk
 
fs_yesharddisk:
call reserve_hd1
 
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
fs_for_new_semantic:
call choice_necessity_partition
 
fs_yesharddisk_all:
mov eax,1
cmp [hdpos],0 ; is hd base set?
jz file_system_return ; no
cmp [fat32part],0 ; is partition set?
jz file_system_return ; no
 
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],'/'
 
jmp file_system_return
 
fs_noharddisk_read:
 
 
cmp dword [esp+20],1 ; WRITE
jne fs_noharddisk_write
 
mov eax,[esp+0] ; /fname
mov byte [eax],0 ; path to asciiz
inc eax ; filename start
 
mov ebx,[esp+12] ; count to write
mov ecx,[esp+8] ; buffer
mov edx,[esp+4]
add edx,12*2 ; path start
 
call file_write
 
mov edi,[esp+0]
mov byte [edi],'/'
 
; eax=0 ok - eax=1 not enough free space
 
jmp file_system_return
 
 
fs_noharddisk_write:
 
cmp dword [esp+20],2 ; DELETE
jne fs_noharddisk_delete
 
mov eax,[esp+0] ; /dirname or /filename
mov byte [eax],0 ; path to asciiz
inc eax ; filename start
mov edx,[esp+4]
add edx,12*2 ; path start
 
call removedir
 
mov edi,[esp+0]
mov byte [edi],'/'
 
jmp file_system_return
 
fs_noharddisk_delete:
 
cmp dword [esp+20],3 ; APPEND
jne fs_noharddisk_append
 
mov eax,[esp+0] ; /dirname or /filename
mov byte [eax],0 ; path to asciiz
inc eax ; filename start
mov edx,[esp+4]
add edx,12*2 ; path start
mov ecx,[esp+8] ; buffer
mov ebx,[esp+12] ; count to write
mov esi,[esp+16] ; bytes to skip over
 
call file_append
 
mov edi,[esp+0]
mov byte [edi],'/'
 
jmp file_system_return
 
fs_noharddisk_append:
 
cmp dword [esp+20],4 ; MAKEDIR
jne fs_noharddisk_makedir
 
mov eax,[esp+0] ; /dirname
mov byte [eax],0 ; path to asciiz
inc eax ; filename start
mov edx,[esp+4]
add edx,12*2 ; path start
 
call makedir
 
mov edi,[esp+0]
mov byte [edi],'/'
 
jmp file_system_return
 
fs_noharddisk_makedir:
 
cmp dword [esp+20],5 ; RENAME
jne fs_noharddisk_rename
 
mov edi,[esp+0] ; start of source file name
add edi,12+1 ; continue after name
call expand_pathz ; convert destination name
 
mov edx,[dir0] ; /HARDDISK
mov eax,[edi+1]
cmp eax,'HD '
je fs_rename_test1
cmp eax,edx
jne fs_rename_error
 
fs_rename_test1:
mov edx,[dir1] ; /FIRST
mov eax,[edi+1+12]
cmp eax,'1 '
je fs_rename_start
cmp eax,edx
jne fs_rename_error
 
fs_rename_start:
mov byte [ebx],0 ; path to asciiz
inc ebx ; filename start
add edi,12*2 ; path start
cmp byte [ebx],0
je fs_rename_error
cmp byte [ebx],32
je fs_rename_error
 
mov eax,[esp+0] ; /filename
mov byte [eax],0 ; path to asciiz
inc eax ; filename start
mov edx,[esp+4]
add edx,12*2 ; path start
 
call rename
 
mov edi,[esp+0]
mov byte [edi],'/'
 
jmp file_system_return
 
fs_rename_error:
mov eax,4 ; partition not defined at hd
jmp file_system_return
 
fs_noharddisk_rename:
 
cmp dword [esp+20],12 ; get FILESIZE
jne fs_noharddisk_get_filesize
 
mov eax,[esp+0] ; /fname
lea edi,[eax+12]
mov byte [eax],0 ; path to asciiz
inc eax ; filename start
mov edx,[esp+4]
add edx,12*2 ; path start
sub edi,edx ; path length
 
call get_filesize
 
mov edi,[esp+0]
mov byte [edi],'/'
 
jmp file_system_return
 
fs_noharddisk_get_filesize:
 
cmp dword [esp+20],13 ; get FILEATTR
jne fs_noharddisk_get_fileattr
 
mov eax,[esp+0] ; /dirname
mov byte [eax],0 ; path to asciiz
inc eax ; filename start
mov edx,[esp+4]
add edx,12*2 ; path start
 
call get_fileattr
 
mov edi,[esp+0]
mov byte [edi],'/'
 
jmp file_system_return
 
fs_noharddisk_get_fileattr:
 
cmp dword [esp+20],14 ; get FILEDATE
jne fs_noharddisk_get_filedate
 
mov eax,[esp+0] ; /dirname
mov byte [eax],0 ; path to asciiz
inc eax ; filename start
mov edx,[esp+4]
add edx,12*2 ; path start
 
call get_filedate
 
mov edi,[esp+0]
mov byte [edi],'/'
 
jmp file_system_return
 
fs_noharddisk_get_filedate:
 
cmp dword [esp+20],16 ; START APPLICATION
jne fs_noharddisk_start_application
 
mov eax,[esp+4] ; fname
add eax,12*2
 
mov ebx,[esp+0] ; length
sub ebx,eax
add ebx,12
 
mov ecx,[esp+4] ; work area
add ecx,512
 
xor ebp,ebp ; parameters to pass
cmp dword [esp+12],0
je no_hd_start_param
mov ebp,[0x3010]
mov ebp,[ebp+0x10]
add ebp,[esp+12]
no_hd_start_param:
 
call start_application_hd
 
jmp file_system_return
 
fs_noharddisk_start_application:
 
fs_noharddisk:
 
file_system_return:
 
add esp,24
 
mov [esp+36],eax
mov [esp+24],ebx
ret
 
 
fs_give_dir1:
 
mov eax,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
 
mov 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,0x100000
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]
 
call wait_for_hd_idle
 
; 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
 
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 [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 err
mov bx,cx
shl cx,1
jc err
shl cx,1
jc err
add cx,bx
jc err
cbw
add cx,ax
jc err
i3:
inc edi
jmp i1
i_exit:
mov ax,cx
clc
i4:
movzx eax,ax
pop edi
pop dx
pop cx
pop bx
ret
 
err:
stc
jmp i4
 
partition_string: dd 0
db 32
/kernel/trunk/fs/fs_phys.inc
0,0 → 1,111
hd_phys_read:
;eax - sector number
;ebx - destination
pushad
call wait_for_hd_idle
popad
push edx
push eax
cli
xor eax,eax
mov edx,[hdbase]
inc edx
out dx,al
inc edx
inc eax
out dx,al
inc edx
;write sector number.
mov eax,[esp]
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] ;+0 or +16
or al,32+64+128
out dx,al
inc edx
mov al,0x20
out dx,al
sti
call wait_for_sector_buffer
cmp [hd_error],0
jnz hd_read_error
cli
push edi
mov edi,ebx
mov ecx,256
mov edx,[hdbase]
cld
rep insw
pop edi
sti
pop edx
pop eax
ret
hd_phys_write:
;eax - sector number
;ebx - destination
cmp eax,[partition_start]
jb .ret
cmp eax,[partition_end]
ja .ret
pushad
call wait_for_hd_idle
popad
push edx
push eax
cli
xor eax,eax
mov edx,[hdbase]
inc edx
out dx,al
inc edx
inc eax
out dx,al
;write sector number
inc edx
mov eax,[esp]
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] ;+0 or +16
or al,32+64+128
out dx,al
inc edx
mov al,0x30
out dx,al
sti
call wait_for_sector_buffer
cmp [hd_error],0
jnz hd_write_error
cli
push esi
mov esi,ebx
mov ecx,256
mov edx,[hdbase]
cld
rep outsw
pop esi
sti
pop edx
pop eax
.ret:
ret