support for PnP disks, part 3: FAT16/FAT32

git-svn-id: svn://kolibrios.org@2643 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
CleverMouse 2012-04-23 09:19:34 +00:00
parent 2643d953b1
commit 46ebef439c
13 changed files with 1246 additions and 1215 deletions

View File

@ -350,8 +350,10 @@ disk_add:
inc eax
cmp byte [ebx+eax-1], 0
jnz @b
; 2b. Call the heap manager.
; 2b. Call the heap manager. Note that it can change ebx.
push ebx
call malloc
pop ebx
; 2c. Check the result. If allocation failed, go to 7.
pop esi ; restore allocated pointer to DISK
test eax, eax
@ -418,7 +420,7 @@ disk_del:
push esi ; save used registers to be stdcall
; 1. Force media to be removed. If the media is already removed, the
; call does nothing.
mov esi, [esp+4+8] ; esi = handle of the disk
mov esi, [esp+4+4] ; esi = handle of the disk
stdcall disk_media_changed, esi, 0
; 2. Delete the structure from the global list.
; 2a. Acquire the mutex.
@ -975,15 +977,33 @@ virtual at ebp+8
.start dq ?
.length dq ?
end virtual
; Currently no file systems are supported, so just allocate the PARTITION
; When disk_add_partition is called, ebx contains a pointer to
; a two-sectors-sized buffer. This function saves ebx in the stack
; immediately before ebp.
virtual at ebp-4
.buffer dd ?
end virtual
; 1. Read the bootsector to the buffer.
mov al, DISKFUNC.read
mov ebx, [.buffer]
add ebx, 512
push 1
stdcall disk_call_driver, ebx, dword [.start], dword [.start+4], esp
; 2. Run tests for all supported filesystems. If at least one test succeeded,
; go to 4.
; For tests: qword [ebp+8] = partition start, qword [ebp+10h] = partition
; length, [esp] = 0 if reading bootsector failed or 1 if succeeded,
; ebx points to the buffer for bootsector.
call fat_create_partition
test eax, eax
jnz .success
; 3. No file system has recognized the volume, so just allocate the PARTITION
; structure without extra fields.
; 1. Allocate and check result.
push sizeof.PARTITION
pop eax
call malloc
test eax, eax
jz .nothing
; 2. Fill the common fields: copy .start and .length.
mov edx, dword [.start]
mov dword [eax+PARTITION.FirstSector], edx
mov edx, dword [.start+4]
@ -992,8 +1012,12 @@ end virtual
mov dword [eax+PARTITION.Length], edx
mov edx, dword [.length+4]
mov dword [eax+PARTITION.Length+4], edx
mov [eax+PARTITION.Disk], esi
and [eax+PARTITION.FSUserFunctions], 0
.success:
.nothing:
; 3. Return with eax = pointer to PARTITION or NULL.
; 4. Return with eax = pointer to PARTITION or NULL.
pop ecx
ret
; This function is called from file_system_lfn.
@ -1061,6 +1085,7 @@ dyndisk_handler:
; 6. Now we are sure that the DISK structure is not going to die at least
; while we are working with it, so release the global mutex.
call mutex_unlock
pop ecx ; pop from the stack saved value of esi
; 7. Acquire the mutex for media object.
pop edi ; restore edi
lea ecx, [ebx+DISK.MediaLock]
@ -1175,15 +1200,36 @@ fs_dyndisk:
.main:
cmp ecx, [edx+DISK.NumPartitions]
jae .notfound
mov dword [esp+32], ERROR_UNKNOWN_FS
mov eax, [edx+DISK.Partitions]
mov eax, [eax+ecx*4]
mov edi, [eax+PARTITION.FSUserFunctions]
test edi, edi
jz .nofs
mov ecx, [ebx]
cmp [edi], ecx
jbe .unsupported
push edx
push ebp
mov ebp, eax
call dword [edi+4+ecx*4]
pop ebp
pop edx
mov dword [esp+32], eax
mov dword [esp+20], ebx
.cleanup:
mov esi, edx
call disk_media_dereference
call disk_dereference
ret
.nofs:
mov dword [esp+32], ERROR_UNKNOWN_FS
jmp .cleanup
.notfound:
mov dword [esp+32], ERROR_FILE_NOT_FOUND
jmp .cleanup
.unsupported:
mov dword [esp+32], ERROR_UNSUPPORTED_FS
jmp .cleanup
.nomedia:
test ecx, ecx
jnz .notfound
@ -1192,7 +1238,6 @@ fs_dyndisk:
; if the driver does not support insert notifications and we are the only fs
; operation with this disk, issue the fake insert notification; if media is
; still not inserted, 'disk_media_changed' will detect this and do nothing
;;; push ebx
lea ecx, [edx+DISK.MediaLock]
call mutex_lock
cmp [edx+DISK.MediaRefCount], 1

View File

@ -18,9 +18,11 @@ fs_read32_sys:
; this request should be processed by hd_read.
cmp [ebp+PARTITION.Disk], 'old'
jnz @f
add eax, dword [ebp+PARTITION.FirstSector]
mov [hdd_appl_data], 0
call hd_read
mov [hdd_appl_data], 1 ; restore to default state
mov eax, [hd_error]
ret
@@:
; In the normal case, save ecx, set ecx to SysCache and let the common part
@ -41,8 +43,11 @@ fs_read32_app:
; this request should be processed by hd_read.
cmp [ebp+PARTITION.Disk], 'old'
jnz @f
add eax, dword [ebp+PARTITION.FirstSector]
mov [hdd_appl_data], 1
jmp hd_read
call hd_read
mov eax, [hd_error]
ret
@@:
; In the normal case, save ecx, set ecx to AppCache and let the common part
; do its work.
@ -63,7 +68,7 @@ fs_read32_common:
ret
@@:
; 2. Get the absolute sector on the disk.
push edx
push edx esi
xor edx, edx
add eax, dword [ebp+PARTITION.FirstSector]
adc edx, dword [ebp+PARTITION.FirstSector+4]
@ -75,15 +80,16 @@ fs_read32_common:
push edx ; startsector
push eax ; startsector
push ebx ; buffer
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.read
call disk_call_driver
pop ecx
pop edx
pop esi edx
pop ecx
ret
.scancache:
; 4. Scan the cache.
push esi edi ecx ; scan cache
push edi ecx ; scan cache
push edx eax
virtual at esp
.sector_lo dd ?
@ -183,9 +189,11 @@ fs_write32_sys:
; this request should be processed by hd_write.
cmp [ebp+PARTITION.Disk], 'old'
jnz @f
add eax, dword [ebp+PARTITION.FirstSector]
mov [hdd_appl_data], 0
call hd_write
mov [hdd_appl_data], 1 ; restore to default state
mov eax, [hd_error]
ret
@@:
; In the normal case, save ecx, set ecx to SysCache and let the common part
@ -206,8 +214,11 @@ fs_write32_app:
; this request should be processed by hd_write.
cmp [ebp+PARTITION.Disk], 'old'
jnz @f
add eax, dword [ebp+PARTITION.FirstSector]
mov [hdd_appl_data], 1
jmp hd_write
call hd_write
mov eax, [hd_error]
ret
@@:
; In the normal case, save ecx, set ecx to AppCache and let the common part
; do its work.
@ -227,7 +238,7 @@ fs_write32_common:
pop ecx
ret
@@:
push edx
push edx esi
; 2. Get the absolute sector on the disk.
xor edx, edx
add eax, dword [ebp+PARTITION.FirstSector]
@ -240,15 +251,16 @@ fs_write32_common:
push edx ; startsector
push eax ; startsector
push ebx ; buffer
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.write
call disk_call_driver
pop ecx
pop edx
pop esi edx
pop ecx
ret
.scancache:
; 4. Scan the cache.
push esi edi ecx ; scan cache
push edi ecx ; scan cache
push edx eax
virtual at esp
.sector_lo dd ?
@ -348,7 +360,7 @@ find_empty_slot64:
jb .found_slot ; it's empty or read
dec ecx
jnz .search_for_empty
call write_cache64 ; no empty slots found, write all
stdcall write_cache64, [ebp+PARTITION.Disk] ; no empty slots found, write all
test eax, eax
jne .found_slot_access_denied
jmp .search_again ; and start again
@ -359,7 +371,7 @@ find_empty_slot64:
ret
; This function is intended to replace the old 'write_cache' function.
proc write_cache64 uses ecx edx esi edi
proc write_cache64 uses ecx edx esi edi, disk:dword
locals
cache_chain_started dd ?
cache_chain_size dd ?
@ -432,8 +444,7 @@ endl
test eax, eax
jnz .nothing
.flush:
mov esi, [ebp]
mov esi, [esi+PARTITION.Disk]
mov esi, [disk]
mov al, DISKFUNC.flush
call disk_call_driver
.nothing:
@ -590,3 +601,21 @@ disk_free_cache:
stdcall kernel_free, eax
.nothing:
ret
; This function flushes all modified data from both caches for the given DISK.
; esi = pointer to DISK
disk_sync:
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure,
; this request should be processed by write_cache.
cmp esi, 'old'
jz write_cache
; The algorithm is straightforward.
push esi
push esi ; for second write_cache64
push esi ; for first write_cache64
add esi, DISK.SysCache
call write_cache64
add esi, DISK.AppCache - DISK.SysCache
call write_cache64
pop esi
ret

View File

@ -945,3 +945,83 @@ int13_call:
@@:
ret
; \end{diamond}
reserve_hd1:
cli
cmp [hd1_status], 0
je reserve_ok1
sti
call change_task
jmp reserve_hd1
reserve_ok1:
push eax
mov eax, [CURRENT_TASK]
shl eax, 5
mov eax, [eax+CURRENT_TASK+TASKDATA.pid]
mov [hd1_status], eax
pop eax
sti
ret
;********************************************
uglobal
hd_in_cache db ?
endg
reserve_hd_channel:
; BIOS disk accesses are protected with common mutex hd1_status
; This must be modified when hd1_status will not be valid!
cmp [hdpos], 0x80
jae .ret
cmp [hdbase], 0x1F0
jne .IDE_Channel_2
.IDE_Channel_1:
cli
cmp [IDE_Channel_1], 0
je .reserve_ok_1
sti
call change_task
jmp .IDE_Channel_1
.IDE_Channel_2:
cli
cmp [IDE_Channel_2], 0
je .reserve_ok_2
sti
call change_task
jmp .IDE_Channel_2
.reserve_ok_1:
mov [IDE_Channel_1], 1
push eax
mov al, 1
jmp @f
.reserve_ok_2:
mov [IDE_Channel_2], 1
push eax
mov al, 3
@@:
cmp [hdid], 1
sbb al, -1
mov [hd_in_cache], al
pop eax
sti
.ret:
ret
free_hd_channel:
; see comment at reserve_hd_channel
cmp [hdpos], 0x80
jae .ret
cmp [hdbase], 0x1F0
jne .IDE_Channel_2
.IDE_Channel_1:
mov [IDE_Channel_1], 0
.ret:
ret
.IDE_Channel_2:
mov [IDE_Channel_2], 0
ret
;********************************************

View File

@ -137,8 +137,6 @@ found_slot_access_denied:
;--------------------------------------------------------------------
align 4
clear_hd_cache:
mov [fat_in_cache], -1
mov [fat_change], 0
ret
;--------------------------------------------------------------------
align 4

View File

@ -38,5 +38,5 @@ end if
ERROR:
prebooting parameters must fit in first sector!!!
end if
hdsysimage db 'KOLIBRI IMG' ; load from
image_save db 'KOLIBRI IMG' ; save to
hdsysimage db 'KOLIBRI.IMG',0 ; load from
image_save db 'KOLIBRI.IMG',0 ; save to

View File

@ -89,13 +89,22 @@ $Revision$
mov [image_retrieved], 1
ret
iglobal
align 4
read_image_fsinfo:
dd 0 ; function: read
dq 0 ; offset: zero
dd 1474560/512 ; size
dd RAMDISK ; buffer
db 0
dd hdsysimage+OS_BASE+0x10000
endg
read_image:
mov eax, hdsysimage+OS_BASE+0x10000
mov ebx, 1474560/512
mov ecx, RAMDISK
mov esi, 0
mov edi, 12
call file_read
mov ebx, read_image_fsinfo
pushad
call file_system_lfn
popad
ret
image_retrieved db 0

View File

@ -133,6 +133,10 @@ end_search_partitions_bd:
loop start_search_partitions_bd
jmp end_search_partitions
problem_partition db 0 ; used for partitions search
include '../fs/part_set.inc'
partition_data_transfer:
mov edi, [transfer_adress]
mov esi, PARTITION_START ;start of file_system_data

View File

@ -95,4 +95,8 @@ kernel_export \
\
LFBAddress,\
GetDisplay,\
SetScreen
SetScreen,\
\
DiskAdd,\
DiskMediaChanged,\
DiskDel

View File

@ -634,31 +634,34 @@ fat_find_lfn:
; [esp+4] = next
; [esp+8] = first
; [esp+C]... - possibly parameters for first and next
; out: CF=1 - file not found
; out: CF=1 - file not found, eax=error code
; else CF=0, esi->next name component, edi->direntry
pusha
lea eax, [esp+0Ch+20h]
call dword [eax-4]
jc .reterr
sub esp, 262*2 ; reserve place for LFN
mov ebp, esp
push 0 ; for fat_get_name: read ASCII name
.l1:
lea ebp, [esp+4]
call fat_get_name
jc .l2
call fat_compare_name
jz .found
.l2:
mov ebp, [esp+8+262*2+4]
lea eax, [esp+0Ch+20h+262*2+4]
call dword [eax-8]
jnc .l1
add esp, 262*2+4
.reterr:
mov [esp+28], eax
stc
popa
ret
.found:
add esp, 262*2+4
mov ebp, [esp+8]
; if this is LFN entry, advance to true entry
cmp byte [edi+11], 0xF
jnz @f

File diff suppressed because it is too large Load Diff

View File

@ -169,10 +169,6 @@ endg
fs_info: ;start of code - Mihasik
push eax
cmp [eax+21], byte 'h'
je fs_info_h
cmp [eax+21], byte 'H'
je fs_info_h
cmp [eax+21], byte 'r'
je fs_info_r
cmp [eax+21], byte 'R'
@ -189,9 +185,6 @@ endg
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
@ -437,32 +430,6 @@ hd_err_return:
jmp file_system_return
@@:
cmp dword [esp+20], 0; READ
jne fs_noharddisk_read
mov eax, [esp+0] ; /fname
lea edi, [eax+12]
mov byte [eax], 0 ; path to asciiz
inc eax ; filename start
mov ebx, [esp+12] ; count to read
mov ecx, [esp+8] ; buffer
mov edx, [esp+4]
add edx, 12*2 ; dir start
sub edi, edx ; path length
mov esi, [esp+16] ; blocks to read
call file_read
mov edi, [esp+0]
mov byte [edi], '/'
call free_hd_channel
and [hd1_status], 0
jmp file_system_return
fs_noharddisk_read:
call free_hd_channel
and [hd1_status], 0

View File

@ -33,24 +33,8 @@ align 4
fs_dependent_data_start:
; FATxx data
SECTORS_PER_FAT dd 0x1f3a
NUMBER_OF_FATS dd 0x2
SECTORS_PER_CLUSTER dd 0x8
BYTES_PER_SECTOR dd 0x200 ; Note: if BPS <> 512 need lots of changes
ROOT_CLUSTER dd 2 ; first rootdir cluster
FAT_START dd 0 ; start of fat table
ROOT_START dd 0 ; start of rootdir (only fat16)
ROOT_SECTORS dd 0 ; count of rootdir sectors (only fat16)
DATA_START dd 0 ; start of data area (=first cluster 2)
LAST_CLUSTER dd 0 ; last availabe cluster
ADR_FSINFO dd 0 ; used only by fat32
fatRESERVED dd 0x0FFFFFF6
fatBAD dd 0x0FFFFFF7
fatEND dd 0x0FFFFFF8
fatMASK dd 0x0FFFFFFF
fatStartScan dd 2
.partition dd ?
rb 80
fs_dependent_data_end:
file_system_data_size = $ - PARTITION_START
@ -427,108 +411,27 @@ boot_read_ok:
cmp [hd_error], 0
jnz problem_fat_dec_count
cmp word [ebx+0x1fe], 0xaa55; is it valid boot sector?
jnz problem_fat_dec_count
movzx eax, word [ebx+0xe]; sectors reserved
add eax, [PARTITION_START]
mov [FAT_START], eax; fat_start = partition_start + reserved
movzx eax, byte [ebx+0xd]; sectors per cluster
push 0
mov eax, [PARTITION_END]
sub eax, [PARTITION_START]
inc eax
push eax
push 0
push [PARTITION_START]
push ebp
push ebp
mov ebp, esp
mov esi, 'old' ; special value: there is no DISK structure
push 1 ; bootsector read successfully
call fat_create_partition
add esp, 4*7
test eax, eax
jz problem_fat_dec_count
mov [SECTORS_PER_CLUSTER], eax
movzx ecx, word [ebx+0xb]; bytes per sector
cmp ecx, 0x200
jnz problem_fat_dec_count
mov [BYTES_PER_SECTOR], ecx
movzx eax, word [ebx+0x11]; count of rootdir entries (=0 fat32)
mov edx, 32
mul edx
dec ecx
add eax, ecx ; round up if not equal count
inc ecx ; bytes per sector
div ecx
mov [ROOT_SECTORS], eax; count of rootdir sectors
movzx eax, word [ebx+0x16]; sectors per fat <65536
test eax, eax
jnz fat16_fatsize
mov eax, [ebx+0x24] ; sectors per fat
fat16_fatsize:
mov [SECTORS_PER_FAT], eax
movzx eax, byte [ebx+0x10]; number of fats
test eax, eax ; if 0 it's not fat partition
jz problem_fat_dec_count
mov [NUMBER_OF_FATS], eax
imul eax, [SECTORS_PER_FAT]
add eax, [FAT_START]
mov [ROOT_START], eax; rootdir = fat_start + fat_size * fat_count
add eax, [ROOT_SECTORS]; rootdir sectors should be 0 on fat32
mov [DATA_START], eax; data area = rootdir + rootdir_size
movzx eax, word [ebx+0x13]; total sector count <65536
test eax, eax
jnz fat16_total
mov eax, [ebx+0x20] ; total sector count
fat16_total:
add eax, [PARTITION_START]
dec eax
mov [PARTITION_END], eax
inc eax
sub eax, [DATA_START]; eax = count of data sectors
xor edx, edx
div dword [SECTORS_PER_CLUSTER]
inc eax
mov [LAST_CLUSTER], eax
dec eax ; cluster count
mov [fatStartScan], 2
; limits by Microsoft Hardware White Paper v1.03
cmp eax, 4085 ; 0xff5
jb problem_fat_dec_count; fat12 not supported
cmp eax, 65525 ; 0xfff5
jb fat16_partition
fat32_partition:
mov eax, [ebx+0x2c] ; rootdir cluster
mov [ROOT_CLUSTER], eax
movzx eax, word [ebx+0x30]; fs info sector
add eax, [PARTITION_START]
mov [ADR_FSINFO], eax
call hd_read
mov eax, [ebx+0x1ec]
cmp eax, -1
jz @f
mov [fatStartScan], eax
@@:
mov [fs_dependent_data_start.partition], eax
mov al, [eax+FAT.fs_type]
mov [fs_type], al
popad
mov [fatRESERVED], 0x0FFFFFF6
mov [fatBAD], 0x0FFFFFF7
mov [fatEND], 0x0FFFFFF8
mov [fatMASK], 0x0FFFFFFF
mov [fs_type], 32 ; Fat32
call free_hd_channel
mov [hd1_status], 0 ; free
ret
fat16_partition:
xor eax, eax
mov [ROOT_CLUSTER], eax
popad
mov [fatRESERVED], 0x0000FFF6
mov [fatBAD], 0x0000FFF7
mov [fatEND], 0x0000FFF8
mov [fatMASK], 0x0000FFFF
mov [fs_type], 16 ; Fat16
call free_hd_channel
mov [hd1_status], 0 ; free
ret

View File

@ -5120,22 +5120,6 @@ socket: ; Socket interface
mov [esp+24], ebx
ret
align 4
read_from_hd: ; Read from hd - fn not in use
mov edi, [TASK_BASE]
add edi, TASKDATA.mem_start
add eax, [edi]
add ecx, [edi]
add edx, [edi]
call file_read
mov [esp+36], eax
mov [esp+24], ebx
ret
paleholder:
ret
;------------------------------------------------------------------------------