103,8 → 103,8 |
fat_create_partition.return0: |
xor eax, eax |
ret |
|
fat_create_partition: |
; sector size must be 512 |
cmp dword [esi+DISK.MediaInfo.SectorSize], 512 |
jnz .return0 |
; bootsector must have been successfully read |
145,19 → 145,14 |
mov [eax+FAT.fat_change], 0 |
push ebp |
mov ebp, eax |
|
lea ecx, [ebp+FAT.Lock] |
call mutex_init |
|
movzx eax, word [ebx+0xe] ; sectors reserved |
mov [ebp+FAT.FAT_START], eax |
|
movzx eax, byte [ebx+0xd] ; sectors per cluster |
mov [ebp+FAT.SECTORS_PER_CLUSTER], eax |
|
movzx ecx, word [ebx+0xb] ; bytes per sector |
mov [ebp+FAT.BYTES_PER_SECTOR], ecx |
|
movzx eax, word [ebx+0x11] ; count of rootdir entries (=0 fat32) |
shl eax, 5 ; mul 32 |
dec ecx |
166,7 → 161,6 |
xor edx, edx |
div ecx |
mov [ebp+FAT.ROOT_SECTORS], eax ; count of rootdir sectors |
|
movzx eax, word [ebx+0x16] ; sectors per fat <65536 |
test eax, eax |
jnz @f |
173,7 → 167,6 |
mov eax, [ebx+0x24] ; sectors per fat |
@@: |
mov [ebp+FAT.SECTORS_PER_FAT], eax |
|
movzx eax, byte [ebx+0x10] ; number of fats |
mov [ebp+FAT.NUMBER_OF_FATS], eax |
mul [ebp+FAT.SECTORS_PER_FAT] |
185,13 → 178,11 |
add eax, [ebp+FAT.ROOT_SECTORS] ; rootdir sectors should be 0 on fat32 |
jc .free_return0 |
mov [ebp+FAT.DATA_START], eax ; data area = rootdir + rootdir_size |
|
movzx eax, word [ebx+0x13] ; total sector count <65536 |
test eax, eax |
jnz @f |
mov eax, [ebx+0x20] ; total sector count |
@@: |
; total sector count must not exceed partition size |
cmp dword [ebp+FAT.Length+4], 0 |
jnz @f |
cmp eax, dword [ebp+FAT.Length] |
208,11 → 199,10 |
dec eax ; cluster count |
jz .free_return0 |
mov [ebp+FAT.fatStartScan], 2 |
|
; limits by Microsoft Hardware White Paper v1.03 |
cmp eax, 4085 ; 0xff5 |
cmp eax, 0xff5 |
jb .fat12 |
cmp eax, 65525 ; 0xfff5 |
cmp eax, 0xfff5 |
jb .fat16 |
.fat32: |
mov eax, [ebx+0x2c] ; rootdir cluster |
246,6 → 236,7 |
mov eax, ebp |
pop ebp |
ret |
|
.fat16: |
and [ebp+FAT.ROOT_CLUSTER], 0 |
mov [ebp+FAT.fatRESERVED], 0x0000FFF6 |
254,6 → 245,7 |
mov [ebp+FAT.fatMASK], 0x0000FFFF |
mov al, 16 |
jmp .fat_not_12_finalize |
|
.fat12: |
and [ebp+FAT.ROOT_CLUSTER], 0 |
mov [ebp+FAT.fatRESERVED], 0xFF6 |
264,7 → 256,6 |
mov [ebp+FAT.fs_type], al |
; For FAT12, allocate&read data for entire table: |
; calculate A = ALIGN_UP(NUM_CLUSTERS, 8), |
; calculatefatchain/restorefatchain will process A items, |
; allocate ALIGN_UP(A*3/2, 512) bytes for FAT table plus A*2 bytes for unpacked data. |
mov eax, [ebp+FAT.LAST_CLUSTER] |
and eax, not 7 |
279,8 → 270,6 |
test eax, eax |
jz .free_return0 |
; Read ALIGN_UP(NUM_CLUSTERS*3/2, 512) bytes. |
; Note that this can be less than allocated, this is ok, |
; overallocation simplifies calculatefatchain/restorefatchain. |
push ebx |
mov [ebp+FAT.fat_cache_ptr], eax |
mov edx, [ebp+FAT.LAST_CLUSTER] |
295,11 → 284,11 |
test eax, eax |
pop eax |
jz @f |
dbgstr 'Failed to read FAT table' |
mov eax, [ebp+FAT.fat_cache_ptr] |
call free |
pop ebx |
jmp .free_return0 |
|
@@: |
add ebx, 512 |
inc eax |
306,47 → 295,29 |
cmp eax, edx |
jb .read_fat |
mov [ebp+FAT.fat12_unpacked_ptr], ebx |
call calculatefatchain |
pop ebx |
mov eax, ebp |
pop ebp |
ret |
|
fat_free: |
push eax |
mov eax, [eax+FAT.fat_cache_ptr] |
call free |
pop eax |
jmp free |
|
calculatefatchain: |
|
pushad |
|
mov esi, [ebp+FAT.fat_cache_ptr] |
mov edi, [ebp+FAT.fat12_unpacked_ptr] |
|
mov edx, [ebp+FAT.LAST_CLUSTER] |
and edx, not 7 |
lea edx, [edi+(edx+8)*2] |
push edx |
|
fcnew: |
@@: |
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 |
shr edx, 4 |
shr dx, 4 |
xor ch, ch |
shld ecx, ebx, 20;6 ok |
shr cx, 4;5 ok |
shld ecx, ebx, 20 |
shr cx, 4 |
shld ebx, eax, 12 |
and ebx, 0x0fffffff;4 ok |
shr bx, 4;3 ok |
and ebx, 0x0fffffff |
shr bx, 4 |
shl eax, 4 |
and eax, 0x0fffffff;2 ok |
shr ax, 4;1 ok |
and eax, 0x0fffffff |
shr ax, 4 |
mov dword [edi], eax |
mov dword [edi+4], ebx |
mov dword [edi+8], ecx |
353,77 → 324,21 |
mov dword [edi+12], edx |
add edi, 16 |
add esi, 12 |
|
cmp edi, [esp] |
jnz fcnew |
jnz @b |
pop eax |
|
popad |
mov eax, ebp |
pop ebx ebp |
ret |
|
|
restorefatchain: ; restore fat chain |
|
pushad |
|
mov esi, [ebp+FAT.fat12_unpacked_ptr] |
mov edi, [ebp+FAT.fat_cache_ptr] |
|
mov edx, [ebp+FAT.LAST_CLUSTER] |
and edx, not 7 |
lea edx, [esi+(edx+8)*2] |
|
fcnew2: |
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 |
mov word [edi+4], bx |
add edi, 6 |
add esi, 8 |
|
cmp esi, edx |
jb fcnew2 |
|
mov esi, [ebp+FAT.NUMBER_OF_FATS] |
mov edx, [ebp+FAT.LAST_CLUSTER] |
lea edx, [(edx+1)*3 + 512*2-1] |
shr edx, 10 |
push [ebp+FAT.FAT_START] |
|
.write_fats: |
xor eax, eax |
mov ebx, [ebp+FAT.fat_cache_ptr] |
.loop1: |
fat_free: |
push eax |
add eax, [esp+4] |
call fs_write32_sys |
test eax, eax |
mov eax, [eax+FAT.fat_cache_ptr] |
call free |
pop eax |
jnz .fail |
add ebx, 512 |
inc eax |
cmp eax, edx |
jb .loop1 |
pop eax |
add eax, [ebp+FAT.SECTORS_PER_FAT] |
push eax |
dec esi |
jnz .write_fats |
pop eax |
jmp free |
|
popad |
ret |
.fail: |
dbgstr 'Failed to save FAT' |
popad |
ret |
|
iglobal |
label fat_legal_chars byte |
; 0 = not allowed |
464,8 → 379,7 |
|
fat_next_short_name: |
; in: edi->8+3 name |
; out: name corrected |
; CF=1 <=> error |
; out: name corrected, CF=1 -> error |
pushad |
mov ecx, 8 |
mov al, '~' |
490,12 → 404,12 |
popad |
clc |
ret |
|
.tilde: |
push edi |
add edi, 7 |
xor ecx, ecx |
@@: |
; after tilde may be only digits and trailing spaces |
@@: ; after tilde may be only digits and trailing spaces |
cmp byte [edi], '~' |
jz .break |
cmp byte [edi], ' ' |
504,14 → 418,17 |
jnz .found |
dec edi |
jmp @b |
|
.space: |
dec edi |
inc ecx |
jmp @b |
|
.found: |
inc byte [edi] |
add dword [esp], 8 |
jmp .zerorest |
|
.break: |
jecxz .noplace |
inc edi |
527,6 → 444,7 |
popad |
clc |
ret |
|
.noplace: |
dec edi |
cmp edi, [esp] |
543,8 → 461,8 |
jb @b |
pop edi |
popad |
;clc ; automatically |
ret |
|
.err: |
pop edi |
popad |
611,6 → 529,7 |
.skip: |
mov bh, 3 |
jmp @f |
|
.firstdot: |
cmp bl, 8 |
jz .space |
620,6 → 539,7 |
mov edi, ecx |
mov bl, 3 |
jmp .loop |
|
.done: |
test bh, 2 |
jz @f |
633,90 → 553,45 |
popad |
ret |
|
fat12_free_space: |
;--------------------------------------------- |
; |
; returns free space in edi |
; rewr.by Mihasik |
;--------------------------------------------- |
|
push eax ebx ecx |
|
mov edi, [ebp+FAT.fat12_unpacked_ptr];start of FAT |
xor ax, ax;Free cluster=0x0000 in FAT |
xor ebx, ebx;counter |
mov ecx, [ebp+FAT.LAST_CLUSTER] |
inc ecx |
cld |
rdfs1: |
repne scasw |
jnz rdfs2 ;if last cluster not 0 |
inc ebx |
test ecx, ecx |
jnz rdfs1 |
rdfs2: |
shl ebx, 9;free clusters*512 |
mov edi, ebx |
|
pop ecx ebx eax |
ret |
|
|
|
set_FAT: |
;-------------------------------- |
; input : EAX = cluster |
; EDX = value to save |
; EBP = pointer to FAT structure |
; output : EDX = old value |
;-------------------------------- |
; out: CF set <=> error |
; in: eax = cluster, edx = value to save |
; out: edx = old value, CF=1 -> error |
push eax ebx esi |
|
cmp eax, 2 |
jb sfc_error |
cmp eax, [ebp+FAT.LAST_CLUSTER] |
ja sfc_error |
jc .ret |
cmp [ebp+FAT.LAST_CLUSTER], eax |
jc .ret |
cmp [ebp+FAT.fs_type], 12 |
je set_FAT12 |
je .FAT12 |
cmp [ebp+FAT.fs_type], 16 |
je sfc_1 |
je @f |
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 |
and esi, eax |
shr eax, 9 |
add eax, [ebp+FAT.FAT_START] |
mov ebx, [ebp+FAT.fat_cache_ptr] |
|
cmp eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory? |
je sfc_in_cache ; yes |
|
cmp [ebp+FAT.fat_change], 0; is fat changed? |
je sfc_no_change ; no |
call write_fat_sector; yes. write it into disk |
jc sfc_error |
|
sfc_no_change: |
mov [ebp+FAT.fat_in_cache], eax; save fat sector |
cmp eax, [ebp+FAT.fat_in_cache] |
je .inCache |
cmp [ebp+FAT.fat_change], 0 |
je @f |
call write_fat_sector |
jc .ret |
@@: |
mov [ebp+FAT.fat_in_cache], eax |
call fs_read32_sys |
test eax, eax |
jne sfc_error |
|
|
sfc_in_cache: |
jne .error |
.inCache: |
cmp [ebp+FAT.fs_type], 16 |
jne sfc_test32 |
|
sfc_set16: |
jne .test32 |
xchg [ebx+esi], dx ; save new value and get old value |
jmp sfc_write |
jmp .write |
|
sfc_test32: |
.test32: |
mov eax, [ebp+FAT.fatMASK] |
|
sfc_set32: |
and edx, eax |
xor eax, -1 ; mask for high bits |
and eax, [ebx+esi] ; get high 4 bits |
723,128 → 598,103 |
or eax, edx |
mov edx, [ebx+esi] ; get old value |
mov [ebx+esi], eax ; save new value |
|
sfc_write: |
mov [ebp+FAT.fat_change], 1; fat has changed |
|
sfc_nonzero: |
.write: |
mov [ebp+FAT.fat_change], 1 |
and edx, [ebp+FAT.fatMASK] |
|
sfc_return: |
.ret: |
pop esi ebx eax |
ret |
sfc_error: |
|
.error: |
stc |
jmp sfc_return |
jmp .ret |
|
set_FAT12: |
.FAT12: |
test edx, 0xF000 |
jnz sfc_error |
jnz .error |
mov ebx, [ebp+FAT.fat12_unpacked_ptr] |
xchg [ebx+eax*2], dx |
mov [ebp+FAT.fat_change], 1 |
pop esi ebx eax |
clc |
ret |
jmp .ret |
|
get_FAT: |
;-------------------------------- |
; input : EAX = cluster |
; EBP = pointer to FAT structure |
; output : EAX = next cluster |
;-------------------------------- |
; out: CF set <=> error |
; in: eax = cluster |
; out: eax = next cluster, CF=1 -> error |
push ebx esi |
|
cmp [ebp+FAT.fs_type], 12 |
je get_FAT12 |
|
je .FAT12 |
cmp [ebp+FAT.fs_type], 16 |
je gfc_1 |
je @f |
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 |
and esi, eax |
shr eax, 9 |
add eax, [ebp+FAT.FAT_START] |
mov ebx, [ebp+FAT.fat_cache_ptr] |
|
cmp eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory? |
je gfc_in_cache |
|
cmp [ebp+FAT.fat_change], 0; is fat changed? |
je gfc_no_change ; no |
call write_fat_sector; yes. write it into disk |
jc hd_error_01 |
|
gfc_no_change: |
cmp eax, [ebp+FAT.fat_in_cache] |
je .inCache |
cmp [ebp+FAT.fat_change], 0 |
je @f |
call write_fat_sector |
jc .ret |
@@: |
mov [ebp+FAT.fat_in_cache], eax |
call fs_read32_sys |
test eax, eax |
jne hd_error_01 |
|
gfc_in_cache: |
jnz .error |
.inCache: |
mov eax, [ebx+esi] |
and eax, [ebp+FAT.fatMASK] |
gfc_return: |
.ret: |
pop esi ebx |
ret |
hd_error_01: |
|
.error: |
stc |
jmp gfc_return |
jmp .ret |
|
get_FAT12: |
.FAT12: |
mov ebx, [ebp+FAT.fat12_unpacked_ptr] |
movzx eax, word [ebx+eax*2] |
pop esi ebx |
clc |
ret |
jmp .ret |
|
|
get_free_FAT: |
;----------------------------------------------------------- |
; output : if CARRY=0 EAX = # first cluster found free |
; if CARRY=1 disk full |
; Note : for more speed need to use fat_cache directly |
;----------------------------------------------------------- |
; out: eax = number of first free cluster, CF=1 -> disk full |
push ecx |
mov ecx, [ebp+FAT.LAST_CLUSTER]; counter for full disk |
mov ecx, [ebp+FAT.LAST_CLUSTER] |
mov eax, [ebp+FAT.fatStartScan] |
cmp [ebp+FAT.fs_type], 12 |
jz get_free_FAT12 |
dec ecx |
cmp eax, 2 |
jb gff_reset |
|
gff_test: |
cmp eax, [ebp+FAT.LAST_CLUSTER]; if above last cluster start at cluster 2 |
jbe gff_in_range |
gff_reset: |
jb .reset |
.test: |
cmp eax, [ebp+FAT.LAST_CLUSTER] |
jbe .inRange |
.reset: |
mov eax, 2 |
|
gff_in_range: |
.inRange: |
push eax |
call get_FAT ; get cluster state |
jc gff_not_found_1 |
|
test eax, eax ; is it free? |
call get_FAT |
jc @f |
test eax, eax |
pop eax |
je gff_found ; yes |
inc eax ; next cluster |
dec ecx ; is all checked? |
jnz gff_test ; no |
|
gff_not_found: |
pop ecx ; yes. disk is full |
je .found |
inc eax |
dec ecx |
jnz .test |
.notFound: |
pop ecx |
stc |
ret |
|
gff_not_found_1: |
@@: |
pop eax |
jmp gff_not_found |
jmp .notFound |
|
gff_found: |
.found: |
lea ecx, [eax+1] |
mov [ebp+FAT.fatStartScan], ecx |
pop ecx |
879,281 → 729,184 |
shr edi, 1 |
mov [ebp+FAT.fatStartScan], edi |
lea eax, [edi-1] |
@@: |
pop edi edx ecx |
ret |
|
.notfound: |
pop edi edx ecx |
stc |
ret |
jmp @b |
|
|
write_fat_sector: |
;----------------------------------------------------------- |
; write changed fat to disk |
;----------------------------------------------------------- |
push eax ebx ecx |
|
mov [ebp+FAT.fat_change], 0 |
mov eax, [ebp+FAT.fat_in_cache] |
cmp eax, -1 |
jz write_fat_not_used |
jz @f |
mov ebx, [ebp+FAT.fat_cache_ptr] |
mov ecx, [ebp+FAT.NUMBER_OF_FATS] |
|
write_next_fat: |
.write_next_fat: |
push eax |
call fs_write32_sys |
test eax, eax |
pop eax |
jnz write_fat_not_used |
|
jnz @f |
add eax, [ebp+FAT.SECTORS_PER_FAT] |
dec ecx |
jnz write_next_fat |
|
write_fat_not_used: |
jnz .write_next_fat |
@@: |
pop ecx ebx eax |
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 |
; out in ax: |
; bits 0-4 = day |
; bits 5-8 = month |
; bits 9-15 = count of years from 1980 |
mov al, 7 |
call fsReadCMOS |
ror eax, 5 |
|
mov al, 0x8 ;month |
out 0x70, al |
in al, 0x71 |
call bcd2bin |
mov al, 8 |
call fsReadCMOS |
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) |
mov al, 9 |
call fsReadCMOS |
add ax, 20 |
rol eax, 9 |
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 |
; out in ax: |
; bits 0-4 = second (the low bit is lost) |
; bits 5-10 = minute |
; bits 11-15 = hour |
mov al, 0 |
call fsReadCMOS |
ror eax, 6 |
|
mov al, 0x2 ;minute |
out 0x70, al |
in al, 0x71 |
call bcd2bin |
mov al, 2 |
call fsReadCMOS |
ror eax, 6 |
|
mov al, 0x4 ;hour |
out 0x70, al |
in al, 0x71 |
call bcd2bin |
mov al, 4 |
call fsReadCMOS |
rol eax, 11 |
ret |
|
|
set_current_time_for_entry: |
;----------------------------------------------------- |
; Set current time/date for file entry |
; input : ebx = file entry pointer |
;----------------------------------------------------- |
push eax |
call get_time_for_file; update files date/time |
mov [ebx+22], ax |
call get_date_for_file |
mov [ebx+24], ax |
pop eax |
ret |
|
|
|
add_disk_free_space: |
;----------------------------------------------------- |
; input : ecx = cluster count |
; Note : negative = remove clusters from free space |
; positive = add clusters to free space |
;----------------------------------------------------- |
test ecx, ecx ; no change |
je add_dfs_no |
cmp [ebp+FAT.fs_type], 32 ; free disk space only used by fat32 |
jne add_dfs_no |
|
; in: ecx = cluster count (signed) |
test ecx, ecx |
je .ret |
cmp [ebp+FAT.fs_type], 32 |
jne .ret |
push eax ebx |
mov eax, [ebp+FAT.ADR_FSINFO] |
lea ebx, [ebp+FAT.fsinfo_buffer] |
call fs_read32_sys |
test eax, eax |
jnz add_not_fs |
|
jnz @f |
cmp dword [ebx+0x1fc], 0xaa550000; check sector id |
jne add_not_fs |
|
jne @f |
add [ebx+0x1e8], ecx |
push [ebp+FAT.fatStartScan] |
pop dword [ebx+0x1ec] |
mov eax, [ebp+FAT.ADR_FSINFO] |
call fs_write32_sys |
; jc add_not_fs |
|
add_not_fs: |
@@: |
pop ebx eax |
|
add_dfs_no: |
.ret: |
ret |
|
|
|
clear_cluster_chain: |
;----------------------------------------------------- |
; input : eax = first cluster |
;----------------------------------------------------- |
; in: eax = first cluster |
push eax ecx edx |
xor ecx, ecx ; cluster count |
|
clean_new_chain: |
cmp eax, [ebp+FAT.LAST_CLUSTER]; end of file |
ja delete_OK |
cmp eax, 2 ; unfinished fat chain or zero length file |
jb delete_OK |
cmp eax, [ebp+FAT.ROOT_CLUSTER]; don't remove root cluster |
jz delete_OK |
|
@@: |
cmp eax, [ebp+FAT.LAST_CLUSTER] |
ja @f |
cmp eax, 2 |
jb @f |
cmp eax, [ebp+FAT.ROOT_CLUSTER] |
jz @f |
xor edx, edx |
call set_FAT ; clear fat entry |
jc access_denied_01 |
call set_FAT |
jc .ret |
inc ecx |
mov eax, edx |
jmp @b |
|
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 |
@@: |
call add_disk_free_space |
clc |
access_denied_01: |
.ret: |
pop edx ecx eax |
ret |
|
|
if 0 |
get_hd_info: |
;----------------------------------------------------------- |
; output : eax = 0 - ok |
; 3 - unknown FS |
; 10 - access denied |
; edx = cluster size in bytes |
; ebx = total clusters on disk |
; ecx = free clusters on disk |
;----------------------------------------------------------- |
cmp [ebp+FAT.fs_type], 16 |
jz info_fat_ok |
cmp [ebp+FAT.fs_type], 32 |
jz info_fat_ok |
xor edx, edx |
xor ebx, ebx |
xor ecx, ecx |
mov eax, ERROR_UNKNOWN_FS |
ret |
|
info_fat_ok: |
; call reserve_hd1 |
|
xor ecx, ecx ; count of free clusters |
mov eax, 2 |
mov ebx, [ebp+FAT.LAST_CLUSTER] |
|
info_cluster: |
push eax |
call get_FAT ; get cluster info |
jc info_access_denied |
|
test eax, eax ; is it free? |
jnz info_used ; no |
inc ecx |
|
info_used: |
pop eax |
inc eax |
cmp eax, ebx ; is above last cluster? |
jbe info_cluster ; no. test next cluster |
|
dec ebx ; cluster count |
imul edx, [ebp+FAT.SECTORS_PER_CLUSTER], 512; cluster size in bytes |
xor eax, eax |
ret |
|
info_access_denied: |
add esp, 4 |
xor edx, edx |
xor ebx, ebx |
xor ecx, ecx |
mov eax, ERROR_ACCESS_DENIED |
ret |
end if |
|
update_disk: |
cmp [ebp+FAT.fat_change], 0 ; is fat changed? |
je upd_no_change |
cmp [ebp+FAT.fat_change], 0 |
jz .noChange |
cmp [ebp+FAT.fs_type], 12 |
jz .fat12 |
;----------------------------------------------------------- |
; write changed fat and cache to disk |
;----------------------------------------------------------- |
|
call write_fat_sector |
jc update_disk_acces_denied |
jmp upd_no_change |
.fat12: |
call restorefatchain |
mov [ebp+FAT.fat_change], 0 |
|
upd_no_change: |
|
push esi |
jc .ret |
.noChange: |
mov esi, [ebp+PARTITION.Disk] |
call disk_sync |
pop esi |
update_disk_acces_denied: |
.ret: |
ret |
|
.fat12: |
mov esi, [ebp+FAT.fat12_unpacked_ptr] |
mov edi, [ebp+FAT.fat_cache_ptr] |
mov edx, [ebp+FAT.LAST_CLUSTER] |
and edx, not 7 |
lea edx, [esi+(edx+8)*2] |
@@: |
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 |
mov word [edi+4], bx |
add edi, 6 |
add esi, 8 |
cmp esi, edx |
jb @b |
mov esi, [ebp+FAT.NUMBER_OF_FATS] |
mov edx, [ebp+FAT.LAST_CLUSTER] |
lea edx, [(edx+1)*3 + 512*2-1] |
shr edx, 10 |
push [ebp+FAT.FAT_START] |
.write_fats: |
xor eax, eax |
mov ebx, [ebp+FAT.fat_cache_ptr] |
.loop1: |
push eax |
add eax, [esp+4] |
call fs_write32_sys |
test eax, eax |
pop eax |
jnz @f |
add ebx, 512 |
inc eax |
cmp eax, edx |
jb .loop1 |
pop eax |
add eax, [ebp+FAT.SECTORS_PER_FAT] |
push eax |
dec esi |
jnz .write_fats |
@@: |
pop eax |
mov [ebp+FAT.fat_change], 0 |
jmp .noChange |
|
fat_lock: |
lea ecx, [ebp+FAT.Lock] |
jmp mutex_lock |
|
fat_unlock: |
lea ecx, [ebp+FAT.Lock] |
jmp mutex_unlock |
1524,7 → 1277,6 |
;---------------------------------------------------------------- |
fat_Read: |
call fat_lock |
push edi |
call hd_find_lfn |
jc .notFound |
test byte [edi+11], 0x10 ; do not allow read directories |
1574,7 → 1326,7 |
push ERROR_END_OF_FILE |
.ret: |
call fat_unlock |
pop eax edi |
pop eax |
xor ebx, ebx |
ret |
|
1691,7 → 1443,7 |
mov byte [esp], ERROR_DEVICE |
.done: |
call fat_unlock |
pop eax edx edi |
pop eax edx |
sub ebx, edx |
ret |
|
1714,26 → 1466,12 |
fat_ReadFolder: |
call fat_lock |
mov eax, [ebp+FAT.ROOT_CLUSTER] |
push edi |
cmp byte [esi], 0 |
jz .doit |
call hd_find_lfn |
jnc .found |
pop edi |
push eax |
call fat_unlock |
pop eax |
or ebx, -1 |
ret |
.found: |
jc .error |
test byte [edi+11], 0x10 ; do not allow read files |
jnz .found_dir |
pop edi |
call fat_unlock |
or ebx, -1 |
mov eax, ERROR_ACCESS_DENIED |
ret |
.found_dir: |
jz .accessDenied |
mov eax, [edi+20-2] |
mov ax, [edi+26] ; eax=cluster |
.doit: |
1762,6 → 1500,7 |
push [ebp+FAT.ROOT_SECTORS] |
push ebx |
jmp .new_sector |
|
@@: |
dec eax |
dec eax |
1857,39 → 1596,54 |
pop ebx |
add esp, 4 |
jmp .new_cluster |
|
.notfound2: |
add esp, 8 |
.notfound: |
add esp, 262*2+4 |
pop esi edi |
mov ebx, [edx+4] |
call fat_unlock |
mov eax, ERROR_DEVICE |
ret |
add esp, 262*2+8 |
push ERROR_DEVICE |
jmp @f |
|
.done: |
add esp, 262*2+4+8 |
mov ebx, [edx+4] |
xor eax, eax |
add esp, 262*2+16 |
pushd 0 |
dec ecx |
js @f |
mov al, ERROR_END_OF_FILE |
mov byte [esp], ERROR_END_OF_FILE |
@@: |
push eax |
mov ebx, [edx+4] |
.ret: |
call fat_unlock |
pop eax |
pop esi edi |
ret |
|
.error: |
push eax |
xor ebx, ebx |
jmp .ret |
|
.accessDenied: |
push ERROR_ACCESS_DENIED |
xor ebx, ebx |
jmp .ret |
|
fat1x_root_next: |
push ecx |
lea ecx, [ebp+FAT.buffer+0x200-0x20] |
cmp edi, ecx |
jae fat1x_root_next_sector |
add edi, 0x20 |
@@: |
pop ecx |
add edi, 0x20 |
ret ; CF=0 |
ret |
|
fat1x_root_next_write: |
push ecx |
lea ecx, [ebp+FAT.buffer+0x200] |
cmp edi, ecx |
jc @b |
call fat1x_root_end_write |
fat1x_root_next_sector: |
; read next sector |
push [ebp+FAT.longname_sec2] |
pop [ebp+FAT.longname_sec1] |
mov ecx, [eax+4] |
1900,11 → 1654,8 |
inc ecx |
mov [eax+4], ecx |
cmp ecx, [ebp+FAT.ROOT_SECTORS] |
jnc fat_notroot_next_err |
pop ecx |
jb fat1x_root_first |
mov eax, ERROR_FILE_NOT_FOUND |
stc |
ret |
fat1x_root_first: |
mov eax, [eax+4] |
add eax, [ebp+FAT.ROOT_START] |
1914,21 → 1665,18 |
call fs_read32_sys |
pop ebx |
test eax, eax |
jnz .readerr |
ret ; CF=0 |
.readerr: |
mov eax, ERROR_DEVICE |
jz @f |
movi eax, ERROR_DEVICE |
stc |
@@: |
ret |
.notfound: |
mov eax, ERROR_FILE_NOT_FOUND |
stc |
ret |
|
fat1x_root_begin_write: |
push edi eax |
call fat1x_root_first |
pop eax edi |
ret |
|
fat1x_root_end_write: |
pusha |
mov eax, [eax+4] |
1937,28 → 1685,25 |
call fs_write32_sys |
popa |
ret |
fat1x_root_next_write: |
|
fat_notroot_next: |
push ecx |
lea ecx, [ebp+FAT.buffer+0x200] |
lea ecx, [ebp+FAT.buffer+0x200-0x20] |
cmp edi, ecx |
jae @f |
jae fat_notroot_next_sector |
add edi, 0x20 |
@@: |
pop ecx |
ret |
@@: |
call fat1x_root_end_write |
jmp fat1x_root_next_sector |
fat1x_root_extend_dir: |
stc |
ret |
|
fat_notroot_next: |
fat_notroot_next_write: |
push ecx |
lea ecx, [ebp+FAT.buffer+0x200-0x20] |
lea ecx, [ebp+FAT.buffer+0x200] |
cmp edi, ecx |
jae fat_notroot_next_sector |
pop ecx |
add edi, 0x20 |
ret ; CF=0 |
jc @b |
push eax |
call fat_notroot_end_write |
pop eax |
fat_notroot_next_sector: |
push [ebp+FAT.longname_sec2] |
pop [ebp+FAT.longname_sec1] |
1972,6 → 1717,14 |
jae fat_notroot_next_cluster |
mov [eax+4], ecx |
jmp @f |
|
fat_notroot_next_err: |
pop ecx |
movi eax, ERROR_FILE_NOT_FOUND |
fat1x_root_extend_dir: |
stc |
ret |
|
fat_notroot_next_cluster: |
push eax |
mov eax, [eax] |
2003,16 → 1756,13 |
stc |
.ret: |
ret |
fat_notroot_next_err: |
pop ecx |
mov eax, ERROR_FILE_NOT_FOUND |
stc |
ret |
|
fat_notroot_begin_write: |
push eax edi |
call fat_notroot_first |
pop edi eax |
ret |
|
fat_notroot_end_write: |
call fat_get_sector |
push ebx |
2020,25 → 1770,17 |
call fs_write32_sys |
pop ebx |
ret |
fat_notroot_next_write: |
push ecx |
lea ecx, [ebp+FAT.buffer+0x200] |
cmp edi, ecx |
jae @f |
pop ecx |
ret |
|
fat_notroot_extend_dir.writeerr: |
pop edx |
@@: |
push eax |
call fat_notroot_end_write |
pop eax |
jmp fat_notroot_next_sector |
ret |
|
fat_notroot_extend_dir: |
push eax |
call get_free_FAT |
jnc .found |
pop eax |
ret ; CF=1 |
.found: |
jc @b |
push edx |
mov edx, [ebp+FAT.fatEND] |
call set_FAT |
2049,17 → 1791,10 |
push edx |
call set_FAT |
pop edx |
jnc @f |
.writeerr: |
pop edx |
pop eax |
stc |
ret |
@@: |
jc .writeerr |
push ecx |
or ecx, -1 |
call add_disk_free_space |
; zero new cluster |
mov ecx, 512/4 |
lea edi, [ebp+FAT.buffer] |
push edi |
2144,10 → 1879,26 |
push fat1x_root_next |
jmp .common1 |
|
.retNotFound: |
movi eax, ERROR_FILE_NOT_FOUND |
jmp .ret1 |
|
.noAccess: |
movi eax, ERROR_ACCESS_DENIED |
.ret1: |
mov [esp+28], eax |
call fat_unlock |
popad |
xor ebx, ebx |
ret |
|
.full: |
movi eax, ERROR_DISK_FULL |
jmp .ret1 |
|
.noroot: |
mov eax, ERROR_ACCESS_DENIED |
cmp byte [edi+1], 0 |
jz .ret1 |
jz .noAccess |
; check existence |
mov byte [edi], 0 |
push edi |
2154,24 → 1905,13 |
call hd_find_lfn |
pop esi |
mov byte [esi], '/' |
jnc @f |
.notfound0: |
mov eax, ERROR_FILE_NOT_FOUND |
.ret1: |
mov [esp+28], eax |
call fat_unlock |
popad |
xor ebx, ebx |
ret |
|
@@: |
jc .retNotFound |
inc esi |
test byte [edi+11], 0x10 ; must be directory |
mov eax, ERROR_ACCESS_DENIED |
jz .ret1 |
test byte [edi+11], 0x10 |
jz .noAccess ; file |
mov edx, [edi+20-2] |
mov dx, [edi+26] ; ebp=cluster |
mov eax, ERROR_FS_FAIL |
mov dx, [edi+26] |
movi eax, ERROR_FS_FAIL |
cmp edx, 2 |
jb .ret1 |
.pushnotroot: |
2205,11 → 1945,7 |
cmp byte [esp+36+28], 0 |
jz @f |
add esp, 36 |
call fat_unlock |
popad |
mov eax, ERROR_ACCESS_DENIED |
xor ebx, ebx |
ret |
jmp .noAccess |
|
@@: ; delete FAT chain |
push edi |
2240,21 → 1976,13 |
jnc .test_short_name_loop |
.disk_full: |
add esp, 12+36 |
call fat_unlock |
popa |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
jmp .full |
|
.notfound: ; generate short name |
call fat_name_is_legal |
jc @f |
add esp, 36 |
call fat_unlock |
popad |
mov eax, ERROR_FILE_NOT_FOUND |
xor ebx, ebx |
ret |
jmp .retNotFound |
|
@@: |
sub esp, 12 |
2321,11 → 2049,8 |
jnc .scan_dir |
.fsfrfe3: |
add esp, 12+8+12+36 |
call fat_unlock |
popad |
mov eax, ERROR_DEVICE |
xor ebx, ebx |
ret |
movi eax, ERROR_DEVICE |
jmp .ret1 |
|
.scan_dir: |
cmp byte [edi], 0 |
2348,11 → 2073,7 |
pop eax |
jnc .scan_dir |
add esp, 12+8+12+36 |
call fat_unlock |
popad |
mov eax, ERROR_DISK_FULL |
xor ebx, ebx |
ret |
jmp .full |
|
.free: |
test ecx, ecx |
2519,6 → 2240,41 |
add esi, ecx |
jmp .writecommon |
|
.writedir: |
push 512 |
lea edi, [ebp+FAT.buffer] |
mov ebx, edi |
mov ecx, [ebp+FAT.SECTORS_PER_CLUSTER] |
shl ecx, 9 |
cmp ecx, [esp+16] |
jnz .writedircont |
dec dword [esp+20] |
push esi |
mov ecx, 32/4 |
rep movsd |
pop esi |
mov dword [edi-32], '. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
push esi |
mov ecx, 32/4 |
rep movsd |
pop esi |
mov dword [edi-32], '.. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov ecx, [esp+20+36] |
cmp ecx, [ebp+FAT.ROOT_CLUSTER] |
jnz @f |
xor ecx, ecx |
@@: |
mov word [edi-32+26], cx |
shr ecx, 16 |
mov [edi-32+20], cx |
jmp .writedircont |
|
.writeshort: |
mov ecx, [esp+12] |
push ecx |
2599,42 → 2355,7 |
popad |
ret |
|
.writedir: |
push 512 |
lea edi, [ebp+FAT.buffer] |
mov ebx, edi |
mov ecx, [ebp+FAT.SECTORS_PER_CLUSTER] |
shl ecx, 9 |
cmp ecx, [esp+16] |
jnz .writedircont |
dec dword [esp+20] |
push esi |
mov ecx, 32/4 |
rep movsd |
pop esi |
mov dword [edi-32], '. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
push esi |
mov ecx, 32/4 |
rep movsd |
pop esi |
mov dword [edi-32], '.. ' |
mov dword [edi-32+4], ' ' |
mov dword [edi-32+8], ' ' |
mov byte [edi-32+11], 10h |
mov ecx, [esp+20+36] |
cmp ecx, [ebp+FAT.ROOT_CLUSTER] |
jnz @f |
xor ecx, ecx |
@@: |
mov word [edi-32+26], cx |
shr ecx, 16 |
mov [edi-32+20], cx |
jmp .writedircont |
|
@@: |
or eax, -1 |
rep stosw |
ret |
2654,7 → 2375,6 |
;---------------------------------------------------------------- |
fat_Write: |
call fat_lock |
push edi |
call hd_find_lfn |
jc .error |
cmp dword [ebx+8], 0 |
2706,7 → 2426,7 |
push eax |
@@: |
call fat_unlock |
pop eax edi |
pop eax |
ret |
|
.eof: |
2950,18 → 2670,9 |
stc |
ret |
|
fat_update_datetime: |
call get_time_for_file |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
ret |
|
;---------------------------------------------------------------- |
fat_SetFileEnd: |
call fat_lock |
push edi |
call hd_find_lfn |
jc .reteax |
; must not be directory |
2972,7 → 2683,11 |
jnz .endOfFile |
push eax ; save directory sector |
; set file modification date/time to current |
call fat_update_datetime |
call get_time_for_file |
mov [edi+22], ax ; last write |
call get_date_for_file |
mov [edi+24], ax ; last write |
mov [edi+18], ax ; last access |
mov eax, [ebx+4] |
cmp eax, [edi+28] |
jb .truncate |
3085,7 → 2800,7 |
push eax |
.ret: |
call fat_unlock |
pop eax edi |
pop eax |
ret |
|
.error_fat: |
3185,7 → 2900,7 |
call fs_write32_app |
pop ebx |
.truncate_done: |
pop ecx eax edi |
pop ecx eax |
call update_disk |
call fat_unlock |
xor eax, eax |
3198,10 → 2913,9 |
mov eax, 2 |
ret |
@@: |
push edi |
call fat_lock |
call hd_find_lfn |
jc .error |
jc @f |
push ebp |
xor ebp, ebp |
mov esi, [ebx+16] |
3208,23 → 2922,18 |
mov dword [esi+4], ebp |
call fat_entry_to_bdfe2 |
pop ebp |
call fat_unlock |
xor eax, eax |
pop edi |
ret |
.error: |
@@: |
push eax |
call fat_unlock |
pop eax |
pop edi |
ret |
|
;---------------------------------------------------------------- |
fat_SetFileInfo: |
push edi |
call fat_lock |
call hd_find_lfn |
jc .error |
jc @f |
push eax |
mov edx, [ebx+16] |
call bdfe_to_fat_entry |
3232,15 → 2941,11 |
lea ebx, [ebp+FAT.buffer] |
call fs_write32_sys |
call update_disk |
call fat_unlock |
pop edi |
xor eax, eax |
ret |
.error: |
@@: |
push eax |
call fat_unlock |
pop eax |
pop edi |
ret |
|
;---------------------------------------------------------------- |
3248,7 → 2953,6 |
call fat_lock |
and [ebp+FAT.longname_sec1], 0 |
and [ebp+FAT.longname_sec2], 0 |
push edi |
call hd_find_lfn |
jc .notFound |
cmp dword [edi], '. ' |
3307,7 → 3011,7 |
push ERROR_DEVICE |
.ret: |
call fat_unlock |
pop eax edi |
pop eax |
ret |
|
.notFound: |
3377,6 → 3081,5 |
call clear_cluster_chain |
call update_disk |
call fat_unlock |
pop edi |
xor eax, eax |
ret |