kolibrios/kernel/trunk/fs/iso9660.inc
Doczom 07d896f571 Krn: Added a new driver for the iso9660 file system
Added a new driver for the iso9660 file system. The driver supports the current version of the disk subsystem and is intended for further translation of IDE ATAPI devices to this driver. The basic version of ISO9660 and the Joliet extension are supported.

git-svn-id: svn://kolibrios.org@10053 a494cfbc-eb01-0410-851d-a64ba20cac60
2024-05-26 15:22:48 +00:00

1780 lines
46 KiB
PHP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CD external functions
; in:
; esi -> path string in UTF-8
; ebx -> parameter structure +4
; ecx = bytes to read
; edx -> buffer
; out:
; eax, ebx = return values for sysfunc 70
iglobal
align 4
fs_CdServices:
dd fs_CdRead
dd fs_CdReadFolder
dd fs_NotImplemented
dd fs_NotImplemented
dd fs_NotImplemented
dd fs_CdGetFileInfo
dd fs_NotImplemented
dd 0
dd fs_NotImplemented
dd fs_NotImplemented
fs_NumCdServices = ($ - fs_CdServices)/4
endg
uglobal
align 4
cd_current_pointer_of_input dd 0
cd_current_pointer_of_input_2 dd 0
cd_mem_location dd 0
cd_counter_block dd 0
cd_status dd 0
endg
;-----------------------------------------------------------------------------
fs_NotImplemented:
movi eax, ERROR_UNSUPPORTED_FS
ret
;-----------------------------------------------------------------------------
reserve_cd:
cli
cmp [cd_status], 0
je reserve_ok2
sti
call change_task
jmp reserve_cd
;-----------------------------------------------------------------------------
reserve_ok2:
push eax
mov eax, [current_slot]
mov eax, [eax + APPDATA.tid]
mov [cd_status], eax
pop eax
sti
ret
;-----------------------------------------------------------------------------
reserve_cd_channel:
pushad
mov eax, [cdpos]
dec eax
shr eax, 2
test eax, eax
jnz .1
cmp [ChannelNumber], 1
jne @f
mov ecx, ide_channel1_mutex
jmp .mutex_lock
;--------------------------------------
@@:
mov ecx, ide_channel2_mutex
jmp .mutex_lock
;--------------------------------------
.1:
dec eax
jnz .2
cmp [ChannelNumber], 1
jne @f
mov ecx, ide_channel3_mutex
jmp .mutex_lock
;--------------------------------------
@@:
mov ecx, ide_channel4_mutex
jmp .mutex_lock
;--------------------------------------
.2:
cmp [ChannelNumber], 1
jne @f
mov ecx, ide_channel5_mutex
jmp .mutex_lock
;--------------------------------------
@@:
mov ecx, ide_channel6_mutex
.mutex_lock:
call mutex_lock
popad
ret
;-----------------------------------------------------------------------------
free_cd_channel:
pushad
mov eax, [cdpos]
dec eax
shr eax, 2
test eax, eax
jnz .1
cmp [ChannelNumber], 1
jne @f
mov ecx, ide_channel1_mutex
jmp .mutex_unlock
;--------------------------------------
@@:
mov ecx, ide_channel2_mutex
jmp .mutex_unlock
;--------------------------------------
.1:
dec eax
jnz .2
cmp [ChannelNumber], 1
jne @f
mov ecx, ide_channel3_mutex
jmp .mutex_unlock
;--------------------------------------
@@:
mov ecx, ide_channel4_mutex
jmp .mutex_unlock
;--------------------------------------
.2:
cmp [ChannelNumber], 1
jne @f
mov ecx, ide_channel5_mutex
jmp .mutex_unlock
;--------------------------------------
@@:
mov ecx, ide_channel6_mutex
.mutex_unlock:
call mutex_unlock
popad
ret
;-----------------------------------------------------------------------------
fs_CdRead:
call cd_find_lfn
jc .notFound
mov edi, [cd_current_pointer_of_input]
test byte [edi+25], 10b ; do not allow read directories
jnz .noaccess
test ebx, ebx
jz .l1
cmp dword [ebx+4], 0
jz @f
xor ebx, ebx
movi eax, ERROR_END_OF_FILE
ret
.notFound:
cmp [DevErrorCode], 0
jne .noaccess
xor ebx, ebx
movi eax, ERROR_FILE_NOT_FOUND
ret
.noaccess_3:
pop eax edx ecx
.noaccess:
xor ebx, ebx
movi eax, ERROR_ACCESS_DENIED
ret
@@:
mov ebx, [ebx]
.l1:
push ecx edx 0
mov eax, [edi+10] ; real size of the file section
sub eax, ebx
jb .eof
cmp eax, ecx
jae @f
mov ecx, eax
pop eax
push ERROR_END_OF_FILE
@@:
mov eax, [edi+2]
mov [CDSectorAddress], eax
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
.new_sector:
test ecx, ecx
jz .done
sub ebx, 2048
jae .next
add ebx, 2048
jnz .incomplete_sector
cmp ecx, 2048
jb .incomplete_sector
; we may read and memmove complete sector
mov [CDDataBuf_pointer], edx
call ReadCDWRetr
cmp [DevErrorCode], 0
jne .noaccess_3
add edx, 2048
sub ecx, 2048
.next:
inc dword [CDSectorAddress]
jmp .new_sector
.eof:
pop eax
push ERROR_END_OF_FILE
.done:
mov ebx, edx
pop eax edx ecx
sub ebx, edx
ret
.incomplete_sector: ; we must read and memmove incomplete sector
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr
cmp [DevErrorCode], 0
jne .noaccess_3
push ecx
add ecx, ebx
cmp ecx, 2048
jbe @f
mov ecx, 2048
@@:
sub ecx, ebx
push edi esi ecx
mov edi, edx
lea esi, [CDDataBuf + ebx]
cld
rep movsb
pop ecx esi edi
add edx, ecx
sub [esp], ecx
pop ecx
xor ebx, ebx
jmp .next
;-----------------------------------------------------------------------------
fs_CdReadFolder:
push edi
call cd_find_lfn
jnc .found
pop edi
cmp [DevErrorCode], 0
jne .noaccess_1
xor ebx, ebx
mov eax, ERROR_FILE_NOT_FOUND
ret
.found:
mov edi, [cd_current_pointer_of_input]
test byte [edi+25], 10b ; do not allow read directories
jnz .found_dir
pop edi
.noaccess_1:
xor ebx, ebx
mov eax, ERROR_ACCESS_DENIED
ret
.end_buffer:
pop edx eax
sub eax, 2048 ; directory is over?
ja .read_to_buffer
mov eax, [cd_counter_block]
mov [edx+8], eax
mov eax, [ebx]
sub [edx+4], eax
xor eax, eax
dec ecx
js @f
mov al, ERROR_END_OF_FILE
@@:
pop ecx edi
mov ebx, [edx+4]
ret
.found_dir:
mov eax, [edi+2] ; eax=cluster
mov [CDSectorAddress], eax
mov eax, [edi+10] ; directory size
push eax ecx
mov edi, edx
mov ecx, 32/4
xor eax, eax
rep stosd
pop ecx eax
mov byte [edx], 1 ; version
mov [cd_mem_location], edx
add [cd_mem_location], 32
mov [cd_counter_block], dword 0
dec dword [CDSectorAddress]
push ecx
.read_to_buffer:
inc dword [CDSectorAddress]
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr ; read sector of directory
cmp [DevErrorCode], 0
jne .noaccess_1
mov [cd_current_pointer_of_input_2], CDDataBuf
push eax edx
.get_names_from_buffer:
call cd_get_name
jc .end_buffer
inc dword [cd_counter_block]
mov eax, [cd_counter_block]
cmp [ebx], eax
jae .get_names_from_buffer
test ecx, ecx
jz .get_names_from_buffer
mov edi, [cd_counter_block]
mov [edx+4], edi
dec ecx
mov esi, ebp
call cd_get_parameters_of_file
add edi, 40
mov ax, '.'
cmp dword[ebx+4], 2
jz .utf16
cmp dword[ebx+4], 3
jz .utf8
cmp [cd_counter_block], 2
jbe .parentDirectory
@@:
lodsw
xchg ah, al
call uni2ansi_char
stosb
call .checkForEnd
jc @b
@@:
mov [edi], byte 0
add [cd_mem_location], 304
jmp .get_names_from_buffer
.parentDirectory:
stosb
cmp [cd_counter_block], 2
jnz @b
stosb
jmp @b
.utf8:
add [cd_mem_location], 256
cmp [cd_counter_block], 2
jbe .parentDirectory
push ecx
mov ecx, 519
@@:
lodsw
xchg ah, al
call UTF16to8
js @f
call .checkForEnd
jc @b
@@:
pop ecx
mov [edi], byte 0
add [cd_mem_location], 304
jmp .get_names_from_buffer
.checkForEnd:
mov ax, [esi]
cmp ax, 3B00h ; ';'
jz @f
; check for files not ending with separator
movzx eax, byte [ebp-33]
add eax, ebp
sub eax, 34
cmp esi, eax
jz @f
; check the end of the directory
movzx eax, byte [ebp-1]
add eax, ebp
cmp esi, eax
@@:
ret
.utf16:
cmp [cd_counter_block], 2
jbe .utf16ParentDirectory
@@:
lodsw
xchg ah, al
stosw
call .checkForEnd
jc @b
@@:
mov [edi], word 0
add [cd_mem_location], 560
jmp .get_names_from_buffer
.utf16ParentDirectory:
stosw
cmp [cd_counter_block], 2
jnz @b
stosw
jmp @b
cd_get_parameters_of_file:
mov edi, [cd_mem_location]
cd_get_parameters_of_file_1:
; get file attributes
xor eax, eax
; file is not archived
inc eax
shl eax, 1
; is a directory?
test [ebp-8], byte 2
jz .file
inc eax
.file:
; not as a volume label in the FAT, in this form not available
; file is not a system
shl eax, 3
; file is hidden? (attribute of existence)
test [ebp-8], byte 1
jz .hidden
inc eax
.hidden:
shl eax, 1
; file is always read-only, as this CD
inc eax
mov [edi], eax
mov eax, [ebx+4]
mov [edi+4], eax
; get the time to file
; hour
movzx eax, byte [ebp-12]
shl eax, 8
; minute
mov al, [ebp-11]
shl eax, 8
; second
mov al, [ebp-10]
; file creation time
mov [edi+8], eax
; last access time
mov [edi+16], eax
; last write time
mov [edi+24], eax
; get date for file
; year
movzx eax, byte [ebp-15]
add eax, 1900
shl eax, 8
; month
mov al, [ebp-14]
shl eax, 8
; day
mov al, [ebp-13]
; file creation date
mov [edi+12], eax
; last access date
mov [edi+20], eax
; last write date
mov [edi+28], eax
; get the file size in bytes
xor eax, eax
mov [edi+32+4], eax
mov eax, [ebp-23]
mov [edi+32], eax
ret
;-----------------------------------------------------------------------------
fs_CdGetFileInfo:
call cd_find_lfn
movi eax, ERROR_FILE_NOT_FOUND
jc @f
mov edi, edx
mov eax, [ebx+4]
mov [edx+4], eax
cmp byte [esi], 0
jz .volume
mov ebp, [cd_current_pointer_of_input]
add ebp, 33
call cd_get_parameters_of_file_1
xor eax, eax
@@:
ret
.volume:
test eax, eax
jz .size
mov ecx, 16
mov esi, CDDataBuf+40
add edi, 40
cmp eax, 2
jz .utf16
cmp eax, 3
jz .utf8
@@:
lodsw
xchg al, ah
call uni2ansi_char
stosb
loop @b
jmp .size
.utf16:
lodsw
xchg al, ah
stosw
loop .utf16
jmp .size
.utf8:
mov ebx, ecx
shl ecx, 1
@@:
lodsw
xchg ah, al
call UTF16to8
dec ebx
jnz @b
.size:
mov eax, [CDDataBuf+80]
shl eax, 11
mov [edx+32], eax
xor eax, eax
mov [edx+36], eax
stosw
mov byte [edx], 8
ret
;-----------------------------------------------------------------------------
cd_find_lfn:
mov [cd_appl_data], 0
; in: esi -> path string in UTF-8
; out: [cd_current_pointer_of_input] -> direntry, CF=1 -> file not found
push eax esi
; Sector 16 - start set of volume descriptors
call WaitUnitReady
cmp [DevErrorCode], 0
jne .access_denied
call prevent_medium_removal
; testing of reading
mov [CDSectorAddress], dword 16
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr;_1
cmp [DevErrorCode], 0
jne .access_denied
; calculation of the last session
call WaitUnitReady
cmp [DevErrorCode], 0
jne .access_denied
call Read_TOC
mov ah, [CDDataBuf+4+4]
mov al, [CDDataBuf+4+5]
shl eax, 16
mov ah, [CDDataBuf+4+6]
mov al, [CDDataBuf+4+7]
add eax, 15
mov [CDSectorAddress], eax
; mov [CDSectorAddress],dword 15
mov [CDDataBuf_pointer], CDDataBuf
;--------------------------------------
.start:
inc dword [CDSectorAddress]
call ReadCDWRetr;_1
cmp [DevErrorCode], 0
jne .access_denied
.start_check:
; checking for "lice"
cmp [CDDataBuf+1], dword 'CD00'
jne .access_denied
cmp [CDDataBuf+5], byte '1'
jne .access_denied
; sector is the terminator of set of descriptors volumes?
cmp [CDDataBuf], byte 0xff
je .access_denied
; sector is an additional and improved descriptor of volume?
cmp [CDDataBuf], byte 0x2
jne .start
; sector is an additional descriptor of volume?
cmp [CDDataBuf+6], byte 0x1
jne .start
; parameters of root directory
mov eax, [CDDataBuf+0x9c+2]; start of root directory
mov [CDSectorAddress], eax
mov eax, [CDDataBuf+0x9c+10]; size of root directory
cmp byte [esi], 0
jnz @f
mov [cd_current_pointer_of_input], CDDataBuf+0x9c
jmp .done
;--------------------------------------
@@:
; start the search
.mainloop:
dec dword [CDSectorAddress]
;--------------------------------------
.read_to_buffer:
inc dword [CDSectorAddress]
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr ; read sector of directory
cmp [DevErrorCode], 0
jne .access_denied
call cd_find_name_in_buffer
jnc .found
sub eax, 2048
; directory is over?
cmp eax, 0
ja .read_to_buffer
; desired element of chain is not found
.access_denied:
pop esi eax
mov [cd_appl_data], 1
stc
ret
;--------------------------------------
; desired element of chain found
.found:
; the end of the file path
cmp byte [esi-1], 0
jz .done
mov eax, [cd_current_pointer_of_input]
push dword [eax+2]
pop dword [CDSectorAddress] ; beginning of the directory
mov eax, [eax+2+8] ; size of directory
jmp .mainloop
;--------------------------------------
; file pointer found
.done:
pop esi eax
mov [cd_appl_data], 1
clc
ret
;-----------------------------------------------------------------------------
cd_find_name_in_buffer:
mov [cd_current_pointer_of_input_2], CDDataBuf
;--------------------------------------
.start:
call cd_get_name
jc .not_found
call cd_compare_name
jc .start
;--------------------------------------
.found:
clc
ret
;--------------------------------------
.not_found:
stc
ret
;-----------------------------------------------------------------------------
cd_get_name:
push eax
mov ebp, [cd_current_pointer_of_input_2]
mov [cd_current_pointer_of_input], ebp
mov eax, [ebp]
test eax, eax ; entry's is over?
jz .next_sector
cmp ebp, CDDataBuf+2048 ; buffer is over?
jae .next_sector
movzx eax, byte [ebp]
add [cd_current_pointer_of_input_2], eax ; next entry of directory
add ebp, 33; pointer is set to the beginning of the name
pop eax
clc
ret
;--------------------------------------
.next_sector:
pop eax
stc
ret
;-----------------------------------------------------------------------------
cd_compare_name:
; in: esi -> UTF-8 name, ebp -> UTF-16BE name
; out: CF=0 -> names match, esi -> next component of name
; CF=1 -> esi is not changed
push edx edi eax esi
mov edi, ebp
.loop:
call utf8to16
call utf16toUpper
mov edx, eax
mov ax, [edi]
xchg al, ah
call utf16toUpper
cmp ax, dx
jne .name_not_coincide
add edi, 2
cmp [esi], byte '/' ; path separator is end of current element
je .done
cmp [esi], byte 0 ; path separator end of name
jne .loop
.done:
; check end of file
cmp [edi], word 3B00h; separator end of file ';'
je .done_1
; check for files not ending with separator
movzx eax, byte [ebp-33]
add eax, ebp
sub eax, 34
cmp edi, eax
je .done_1
; check the end of directory
movzx eax, byte [ebp-1]
add eax, ebp
cmp edi, eax
jne .name_not_coincide
.done_1:
pop eax eax edi edx
inc esi
ret
.name_not_coincide:
pop esi eax edi edx
stc
ret
;;; New driver
DESCRIPTOR_TYPE_BOOT = 0x00 ; not used
DESCRIPTOR_TYPE_PRIMARY = 0x01
DESCRIPTOR_TYPE_SUPPLEMENTARY = 0x02
; DESCRIPTOR_TYPE_PRIMARY for Juliet(UTF-16)
DESCRIPTOR_TYPE_PARTITION = 0x02
DESCRIPTOR_TYPE_TERMANATOR = 0xff ; end scan descriptors
struct ISO9660_VOLUME_DESCRIPTOR
type rb 1
magic rb 5 ; 'CD001'
version rb 1
ends
struct ISO9660_PRIMARY_DESCRIPTOR ISO9660_VOLUME_DESCRIPTOR
rb 1
rb 32
VolumeName rb 32 ; ascii or utf-16
rb 8
VolumeSpaceSize rb 8
rb 32
rb 4 ; +120
rb 4
LBA_Size rb 4 ; +128
PathTableSize rb 8 ; Do not use it!!!
LBA_PathTable rb 4 ; +140 ; Do not use it!!!
rb 4 ; +144 ; Do not use it!!!
rb 8
root_dir_record rb 34 ;ISO9660_DIRECTORY_RECORD
rb 128*4 + 37*3
date_created rb 17
date_modiffed rb 17
rb 17
file_struct_ver rb 1 ;always 0x01
ends
struct ISO9660_DIRECTORY_RECORD
size rb 1
rb 1
lba rd 1
rd 1
data_length rd 1
rd 1
date_time rb 7
flags rb 1 ; 10b - directory 1b - hidden
rb 2+4
name_len rb 1
name rb 1 ; rb [name_len]
ends
; Internal data for every ISO9660 partition.
struct ISO9660 PARTITION
type_encoding rd 1 ; 0 - ascii 1 - UCS-2
lba_size rd 1 ; default 2048 TODO
primary_descr rd 1 ; sector num
root_dir_lba rd 1 ; lba32
root_dir_len rd 1 ;
ends
;-----------------------------------------------------------------------------
; ISO9660 external functions
; in:
; ebx -> parameter structure of sysfunc 70
; ebp -> ISO9660 structure
; esi -> path string in UTF-8
; out:
; eax, ebx = return values for sysfunc 70
iglobal
align 4
iso9660_user_functions:
dd iso9660_free
dd (.end - $ - 4) / 4
dd iso9660_Read
dd iso9660_ReadFolder
dd 0
dd 0
dd 0
dd iso9660_GetFileInfo
.end:
endg
; mount if it's a valid ISO9660 partition
iso9660_create_partition:
; in:
; ebp -> PARTITION structure
; ebx -> boot sector
; ebx + 2048 -> buffer
; esi -> DISK structure
; out:
; eax -> iso9660 partition structure, 0 = not iso9660
cmp dword [esi + DISK.MediaInfo.SectorSize], 2048 ; cd disks
jnz .fail_disk_sector
push ebx
sub esp, 4*3 ; locals value: primary_lba, encoding, select_sector
mov dword[esp], 16-1 ; sector number
mov eax, [esi + DISK.MediaInfo.LastSessionSector]
add [esp], eax
mov dword[esp + 4], 0 ; base encoding - ascii
add ebx, 2048
.new_descr:
inc dword[esp]
; read 16 sector, check header of descriptor
xor edx, edx
mov eax, [esp]
mov ecx, 1
; ebx - buffer
; edx:eax - num sector
; ebp - PARTITION
; ecx - number sectors
call fs_read64_sys
test eax, eax
jnz .err_disk_1
cmp dword[ebx + 1], 'CD00'
jnz .err_disk_1
cmp byte[ebx + 5], '1'
jnz .err_disk_1
cmp byte[ebx], DESCRIPTOR_TYPE_TERMANATOR
jz .end_scan
cmp byte[ebx], DESCRIPTOR_TYPE_PRIMARY
jnz @f
cmp dword[esp + 4], 0
jnz .new_descr
mov dword[esp + 4], 0 ; set UCS-2 encoding
mov eax, [esp]
mov dword[esp + 8], eax ; set lba address
jmp .new_descr
@@:
cmp byte[ebx], DESCRIPTOR_TYPE_SUPPLEMENTARY
jnz .new_descr
mov dword[esp + 4], 1 ; set UCS-2 encoding
mov eax, [esp]
mov dword[esp + 8], eax ; set lba address
jmp .new_descr
.end_scan:
; get root dir lba, root dir size, size lba
xor edx, edx
mov eax, [esp + 8]
mov ecx, 1
call fs_read64_sys
test eax, eax
jnz .err_disk_1
; alloc memory for ISO9660 struct
mov eax, sizeof.ISO9660
call malloc
test eax, eax
jz .err_disk_1
; copy data on struct
add esp, 4
pop dword[eax + ISO9660.type_encoding]
mov dword[eax + ISO9660.lba_size], 2048 ;TODO
pop dword[eax + ISO9660.primary_descr]
mov ecx, dword[ebx + ISO9660_PRIMARY_DESCRIPTOR.root_dir_record + ISO9660_DIRECTORY_RECORD.lba]
mov [eax + ISO9660.root_dir_lba], ecx
mov ecx, dword[ebx + ISO9660_PRIMARY_DESCRIPTOR.root_dir_record + ISO9660_DIRECTORY_RECORD.data_length]
mov [eax + ISO9660.root_dir_len], ecx
push edi esi
mov edi, eax
mov esi, ebp
mov ecx, sizeof.PARTITION/4
rep movsd
pop esi edi
mov [eax + PARTITION.FSUserFunctions], iso9660_user_functions
pop ebx
ret
.err_disk_1:
add esp, 4*3
pop ebx
.fail_disk_sector:
xor eax, eax
ret
; IN: eax - ptr PARTITION
; OUT: -
; SAVE: esi, edi
; Function free PARTITION struct and all object this structure
iso9660_free:
jmp free
;-----------------------------------------------------------------------------
; ISO9660 external functions
; in:
; ebx -> parameter structure of sysfunc 70
; ebp -> ISO9660 structure
; esi -> path string in UTF-8
; out:
; eax, ebx = return values for sysfunc 70
iso9660_Read:
sub esp, 4 ; for ptr on memory page
call iso9660_find_file
mov esi, eax
mov edi, [ebx + 16] ; ptr to programm buffer
test byte[esi + ISO9660_DIRECTORY_RECORD.flags], 10b ; check dir
jnz iso9660_find_file.not_found
; check offset (offset <= size)
mov edx, [ebx + 4] ; low offset
cmp dword[ebx + 8], 0 ; high offset
jnz iso9660_find_file.bad_offset ; error offset > max size
cmp edx, [esi + ISO9660_DIRECTORY_RECORD.data_length]
jae iso9660_find_file.bad_offset ; error offset > file length
; good file - copy file data
sub esp, 4*4
mov dword[esp + 3*4], 0
mov [esp + 1*4], edx ; offset to start copy
mov dword[esp], 0 ; count copping byte
; check end offset (offset+size_buff <= size)
mov ecx, [esi + ISO9660_DIRECTORY_RECORD.data_length]
mov eax, [ebx + 12] ;size copy data - buffer size
sub ecx, edx
mov [esp + 2*4], eax ; set count copy = buffer size
cmp ecx, eax ; max copy size > buffer size
jae @f
mov [esp + 2*4], ecx
mov dword[esp + 3*4], ERROR_END_OF_FILE
@@:
mov esi, [esi + ISO9660_DIRECTORY_RECORD.lba]
; [esp + 4*4] = ptr temp buffer
; [esp+3*4] = fs err code [esp+2*4] = size copy data
; [esp+1*4] = offset copy [esp] = count copying data
.full_size:
; check offset mod sector_size = 0
test edx, not -2048
jz .first_align ; no creat buffer for first align
mov ebx, [esp + 4*4]
; read sector
push edx
and edx, -2048
shr edx, BSF 2048
mov eax, esi ; ISO9660_DIRECTORY_RECORD.lba
add eax, edx
mov ecx, 1
xor edx, edx
; ebx - buffer
; edx:eax - num sector
; ebp - PARTITION
; ecx - number sectors
call fs_read64_app
pop edx
test eax, eax
jnz .err_disk_1
mov ecx, edx
neg edx
and edx, not -2048
and ecx, not -2048
; create new offset
add dword[esp + 1*4], not -2048
and dword[esp + 1*4], -2048
cmp dword[esp + 2*4], edx ; copy data > read in this sector
jae @f
mov edx, [esp + 2*4]
@@:
sub dword[esp + 2*4], edx
add dword[esp], edx
;DEBUGF 1, "K : iso c=%x d=%x Hz\n", ecx, edx
push esi
; copy (2048 - offset) and -2048
mov esi, ebx ; buffer
add esi, ecx
mov ecx, edx
rep movsb
pop esi
;stdcall kernel_free, ebx
.first_align:
mov ecx, [esp + 2*4]
and ecx, -2048
cmp ecx, 2048
jb .copy_finish_block
mov eax, [esp + 1*4]
shr eax, BSF 2048
; copy main block
mov ebx, edi
add edi, ecx
sub dword[esp + 2*4], ecx
add dword[esp + 1*4], ecx
add dword[esp], ecx
shr ecx, BSF 2048
xor edx, edx
add eax, esi ; ISO9660_DIRECTORY_RECORD.lba
; ebx - buffer
; edx:eax - num sector
; ebp - PARTITION
; ecx - number sectors
call fs_read64_app
test eax, eax
jnz .err_disk
.copy_finish_block:
cmp dword[esp + 2*4], 0
jz .end_align ; creat buffer for end read sector
mov ebx, [esp + 4*4]
;copy finish block
mov eax, [esp + 1*4]
shr eax, BSF 2048
xor edx, edx
mov ecx, 1
add eax, esi ; ISO9660_DIRECTORY_RECORD.lba
; ebx - buffer
; edx:eax - num sector
; ebp - PARTITION
; ecx - number sectors
call fs_read64_app
test eax, eax
jnz .err_disk_1
mov esi, ebx
mov ecx, [esp + 2*4]
add dword[esp], ecx
rep movsb
;stdcall kernel_free, ebx
.end_align:
; set ebx size copy data
mov ebx, [esp]
mov esi, [esp + 3*4]
add esp, 4*4
call kernel_free
mov eax, esi
ret
.err_disk_1:
stdcall kernel_free, ebx
.err_disk:
add esp, 4*4
call kernel_free
xor ebx, ebx
mov eax, ERROR_DEVICE
ret
;-----------------------------------------------------------------------------
; ISO9660 external functions
; in:
; ebx -> parameter structure of sysfunc 70
; ebp -> ISO9660 structure
; esi -> path string in UTF-8
; out:
; eax, ebx = return values for sysfunc 70
iso9660_ReadFolder:
sub esp, 4 ; for ptr on memory page
call iso9660_find_file
test byte[eax + ISO9660_DIRECTORY_RECORD.flags], 10b ; check dir
jz iso9660_find_file.not_found
mov edi, [ebx + 16] ; buffer
push dword[ebx + 16]
push dword[ebx + 4] ; first file
push dword[ebx + 8] ; encoding
push dword 0
push dword 0
push dword[ebx + 12] ; count file
push dword[eax + ISO9660_DIRECTORY_RECORD.data_length]
push dword[eax + ISO9660_DIRECTORY_RECORD.lba]
; [esp] - lba [esp + 4] - size
; [esp + 8] - max count
; [esp + 12] - counter
; [esp + 16] - all count files
; [esp + 20] - encoding
; [esp + 24] - first item 0..(2^32 -1)
; [esp + 28] - user buffer
; edi - user buffer
; set header(32 byte) in buffer
mov dword[edi], 1
add edi, 32 ;set on first item
; loop copy file info and name
.read_sector:
mov ebx, [esp + 32]
mov ecx, 1
xor edx, edx
mov eax, [esp]
; ebx - buffer
; edx:eax - num sector
; ebp - PARTITION
; ecx - number sectors
call fs_read64_sys
test eax, eax
jnz .err_disk
.new_file:
cmp byte[ebx], 0
jz .next_sector
; inc counter all files
inc dword[esp + 16]
; check copy
mov eax, [esp + 24]
cmp [esp + 16], eax
jbe .skip
mov eax, [esp + 12]
cmp [esp + 8], eax
je .skip
inc dword[esp + 12]
mov eax, ebx
mov ecx, edi
call iso9660_GetFileInfo.copy_file_info
; copy encoding
movzx eax, byte[esp + 20]
mov [edi + 4], eax
add edi, 40
;-----------------------------------------------------------------------------
; copy name
push ebx
push edi
push eax
add ebx, ISO9660_DIRECTORY_RECORD.name
mov esi, ebx
mov cl, [ebx - 1]
cmp cl, 1
jne @f
cmp byte[ebx], 0
jne @f
mov dword[edi], '.'
jmp .end_copy
@@:
cmp cl, byte[ebx]
jne @f
mov dword[edi], '..'
cmp eax, 2
jne .end_copy
mov dword[edi], ('.' shl 16) + '.'
mov word[edi+ 2], 0
jmp .end_copy
@@:
;-----------------------------------------------------------------------------
; copy real name
movzx ecx, byte[ebx - 1]
cmp [ebp + ISO9660.type_encoding], 0
jnz .ucs2
cmp eax, 2
je .ascii2utf16
@@:
sub ecx, 1 ; CF + ZF
jbe @f
movsd
cmp byte[esi], ';'
jne @b
@@:
mov byte[edi], 0
jmp .end_copy
;-----------------------------------------------------------------------------
.ascii2utf16:
lodsb
call ansi2uni_char
stosw
cmp byte[esi], ';'
je @f
loop .ascii2utf16
@@:
mov word[edi], 0
jmp .end_copy
;-----------------------------------------------------------------------------
.ucs2:
shr ecx, 1
cmp eax, 1
ja .ucs2utf16
; convert ucs2 to ascii
@@:
lodsw
cmp ax, 0x3B00
je @f
xchg al, ah
call uni2ansi_char
stosb
loop @b
@@:
mov byte[edi], 0
jmp .end_copy
;-----------------------------------------------------------------------------
.ucs2utf16:
cmp edx, 2 ; utf16 encoding
jne .ucs2utf8
; convert ucs2 to utf16LE
@@:
lodsw
cmp ax, 0x3B00
je @f
xchg al, ah
stosw
loop @b
@@:
mov word[edi], 0
jmp .end_copy
;-----------------------------------------------------------------------------
.ucs2utf8:
; convert ucs2 to utf8
mov ebx, ecx
shl ecx, 1
@@:
lodsw
cmp ax, 0x3B00
je @f
xchg ah, al
call UTF16to8
dec ebx
jnz @b
@@:
mov byte[edi], 0
;-----------------------------------------------------------------------------
.end_copy:
pop eax
pop edi
pop ebx
add edi, 264
cmp eax, 2
jb .skip
add edi, 520-264
.skip:
movzx ecx, byte[ebx]
add ebx, ecx
test ebx, 2048
jnz .next_sector
mov eax, ebx
and eax, not -2048
cmp eax, [esp + 4]
jb .new_file
mov eax, [esp + 12]
cmp eax, [esp + 8]
jb .new_file
jmp .end_loop
.next_sector:
inc dword[esp]
sub dword[esp + 4], 2048
ja .read_sector
.end_loop:
mov ecx, [esp + 28]
mov ebx, [esp + 12]
mov [ecx + 4], ebx
mov esi, [esp + 16]
mov [ecx + 8], esi
mov esi, [esp + 8] ; max count
; free buffer
add esp, 8*4
call kernel_free
xor eax, eax
cmp ebx, esi
je @f
mov eax, ERROR_END_OF_FILE
@@:
ret
.err_disk:
mov ecx, [esp + 28]
mov ebx, [esp + 12]
mov [ecx + 4], ebx
mov esi, [esp + 16]
mov [ecx + 8], esi
; free buffer
add esp, 8*4
call kernel_free
mov eax, ERROR_DEVICE
ret
;-----------------------------------------------------------------------------
; ISO9660 external functions
; in:
; ebx -> parameter structure of sysfunc 70
; ebp -> ISO9660 structure
; esi -> path string in UTF-8
; out:
; eax, ebx = return values for sysfunc 70
iso9660_GetFileInfo:
cmp byte[esi], 0
jz .rootdir
sub esp, 4 ; for ptr on memory page
call iso9660_find_file
mov ecx, [ebx + 16] ; buffer
call .copy_file_info
call kernel_free
xor eax, eax
mov ebx, 40
ret
; IN: eax -> ISO966_DIRECTORY_RECORD
; ecx -> buffer
; destruct: edx
.copy_file_info:
; copy size
mov [ecx + 36], dword 0
mov edx, [eax + ISO9660_DIRECTORY_RECORD.data_length]
mov [ecx + 32], edx
; copy flags(dir of file)
xor edx, edx
or dl, 000001b
test byte[eax + ISO9660_DIRECTORY_RECORD.flags], 1b ; check hidden flag
jz @f
or dl, 10b
@@:
test byte[eax + ISO9660_DIRECTORY_RECORD.flags], 10b ; check dir
jz @f
or dl, 10000b ; dir flag
mov dword[ecx + 32], 0 ; size = zero
@@:
mov [ecx], edx
; copy date creat file
movzx edx, byte[eax + ISO9660_DIRECTORY_RECORD.date_time]
add edx, 1900 ; year
shl edx, 8
mov dl, byte[eax + ISO9660_DIRECTORY_RECORD.date_time + 1] ;month
shl edx, 8
mov dl, byte[eax + ISO9660_DIRECTORY_RECORD.date_time + 2] ;day
mov [ecx + 12], edx
mov [ecx + 20], edx
mov [ecx + 28], edx
; copy time creat file
movzx edx, byte[eax + ISO9660_DIRECTORY_RECORD.date_time + 3] ;hour
shl edx, 8
mov dl, byte[eax + ISO9660_DIRECTORY_RECORD.date_time + 4] ; minute
shl edx, 8
mov dl, byte[eax + ISO9660_DIRECTORY_RECORD.date_time + 5] ; second
mov [ecx + 8], edx
mov [ecx + 16], edx
mov [ecx + 24], edx
ret
.rootdir:
mov edi, [ebx + 16] ; edi = buffer
; copy flags (dir)
mov byte [edi], 8
; copy size drive
mov eax, dword[ebp + PARTITION.Length+DQ.lo]
mov edx, dword[ebp + PARTITION.Length+DQ.hi]
mov ecx, [ebp + PARTITION.Disk]
mov ecx, [ecx + DISK.MediaInfo.SectorSize]
bsf ecx, ecx
shld edx, eax, cl
shl eax, cl
mov [edi + 32], eax ; bdfe.size.lo
mov [edi + 36], edx ; bdfe.size.hi
mov eax, [ebx + 8]
; copy encoding
mov [edi + 4], eax
; check encoding on fs struct
test eax, eax ; check f70s5arg.xflags
jz .no_name
; stdcall is_region_userspace, edi, ecx
; alloc memory for read primary descriptor
stdcall kernel_alloc, PAGE_SIZE
test eax, eax
jz .no_memory
push eax
mov esi, eax
; read primary descriptor
mov ebx, eax
mov ecx, 1
xor edx, edx
mov eax, [ebp + ISO9660.primary_descr]
; ebx - buffer
; edx:eax - num sector
; ebp - PARTITION
; ecx - number sectors
call fs_read64_sys
test eax, eax
jnz .err_read_part
add esi, ISO9660_PRIMARY_DESCRIPTOR.VolumeName
mov edx, [edi + 4]
add edi, 40 ; offset partition name
mov ecx, 32
call iso9660_copy_name
; free memory
call kernel_free
.no_name:
xor eax, eax
mov ebx, 40
ret
.err_read_part:
call kernel_free
mov eax, ERROR_DEVICE
ret
.no_memory:
mov eax, TASKMAN_ERROR_OUT_OF_MEMORY
ret
;-----------------------------------------------------------------------------
; IN: esi - ptr string UTF-8 or zero for root directory
; OUT: eax - ptr to directory record
; [esp + 4] - ptr to memory page for destruct
iso9660_find_file:
stdcall kernel_alloc, 4096 ;
test eax, eax
jz .err_get_memory
mov [esp + 4], eax
cmp byte[esi], 0
jz .rootdir
push ebx ; save and buffer = esp + 8
push dword[ebp + ISO9660.root_dir_len]
push dword[ebp + ISO9660.root_dir_lba]
; [esp] - sector num [esp + 4] - size dir
; [esp + 8] - ebx [esp + 16] - buffer
; get size root dir (not record size)
.read_sector:
; get sector for directory
mov edi, [esp + 16]
mov ebx, [esp + 16]
mov ecx, 1
xor edx, edx
mov eax, [esp]
; ebx - buffer
; edx:eax - num sector
; ebp - PARTITION
; ecx - number sectors
call fs_read64_sys
test eax, eax
jnz .err_disk_1
mov ecx, [esp + 4]
.next_record:
; check size
cmp byte[edi], 0
jz .next_sector
; check file name
call iso9660_compare_name
jnc .found
movzx edx, byte[edi + ISO9660_DIRECTORY_RECORD.size]
add edi, edx
test edi, 2048 ;worked for allocate of page
jnz .next_sector
sub ecx, edx
jc .not_found_2
jmp .next_record
.next_sector:
sub dword[esp + 4], 2048
jbe .not_found_2
inc dword[esp]
jmp .read_sector
.found:
; finish name?
cmp byte[esi], '/'
jne .done
inc esi
mov edx, [edi + ISO9660_DIRECTORY_RECORD.lba]
mov dword[esp], edx
mov edx, [edi + ISO9660_DIRECTORY_RECORD.data_length]
mov dword[esp + 4], edx
jmp .read_sector
.done:
mov ebx, [esp + 8]
add esp, 4*3
mov eax, edi
ret
;-----------------------------------------------------------------------------
.rootdir:
; read primary descriptor
pusha
mov ebx, eax
mov ecx, 1
xor edx, edx
mov eax, [ebp + ISO9660.primary_descr]
; ebx - buffer
; edx:eax - num sector
; ebp - PARTITION
; ecx - number sectors
call fs_read64_sys
test eax, eax
popa
jnz .err_disk
mov eax, [esp + 4]
add eax, ISO9660_PRIMARY_DESCRIPTOR.root_dir_record
ret
; errors
.err_disk_1:
; free stack values
mov ebx, [esp + 8]
add esp, 4*3
.err_disk:
add esp, 4
call kernel_free
xor ebx, ebx
mov eax, ERROR_DEVICE
ret
.not_found_2:
mov ebx, [esp + 8]
add esp, 4*3
.not_found_1:
add esp, 4
.not_found: ; [esp] - ptr to page
call kernel_free
mov eax, ERROR_FILE_NOT_FOUND
xor ebx, ebx
ret
.bad_offset: ; [esp] - ptr to page
call kernel_free
mov eax, ERROR_END_OF_FILE
xor ebx, ebx
ret
.err_get_memory:
add esp, 8 ; skip addr return and dword for ptr to buffer
.no_memory:
mov eax, TASKMAN_ERROR_OUT_OF_MEMORY
xor ebx, ebx
ret
iso9660_compare_name:
; in: esi -> UTF-8 name, ebp -> ISO9660 struct
; edi -> ISO9660_DIRECTORY_RECORD
; out: CF=0 -> names match, esi -> next component of name
; CF=1 -> esi is not changed
push ecx eax esi edi
add edi, ISO9660_DIRECTORY_RECORD.name
.loop:
call utf8to16
call utf16toUpper
mov edx, eax
mov ax, [edi]
cmp [ebp + ISO9660.type_encoding], 0
jnz @f
shl ax, 8 ; ah=al al=0
dec edi
@@:
xchg al, ah
call utf16toUpper
cmp ax, dx
jne .name_not_coincide
add edi, 2
cmp byte[esi], '/' ; path separator is end of current element
je .done
cmp byte[esi], 0 ; path separator end of name
jne .loop
.done:
; check end of file
cmp [ebp + ISO9660.type_encoding], 0
jnz @f
cmp byte[edi], ';'
je .done_1
@@:
cmp [ebp + ISO9660.type_encoding], 0
jz @f
cmp word[edi], 0x3B00; separator end of file ';'
je .done_1
@@:
; check for files not ending with separator
; movzx eax, byte [ebp-33]
; add eax, ebp
; sub eax, 34
; cmp edi, eax
; je .done_1
; check the end of directory
mov ecx, [esp]
movzx eax, byte [ecx + ISO9660_DIRECTORY_RECORD.name_len]
add ecx, ISO9660_DIRECTORY_RECORD.name
add eax, ecx
cmp edi, eax
jne .name_not_coincide
.done_1:
pop edi eax eax ecx
ret
.name_not_coincide:
pop edi esi eax ecx
stc
ret
;IN: ebp -> PARTITION structure
; ebx -> FS structure
; esi -> input string (ascii or ucs2)
; ecx = count bytes
; edi -> output string (buffer)
; edx = encoding output string
;OUT: edi increasing
; esi increasing
; ecx = 0 or other value
iso9660_copy_name:
cmp [ebp + ISO9660.type_encoding], 0
jnz .ucs2
cmp edx, 1 ; cp866 encoding
jne @f
; no convert chars
rep movsb
jmp .end_copy_name
@@:
cmp edx, 2 ; utf16 encoding
jne .ascii2utf8
; convert ascii to utf16LE
@@:
lodsb
call ansi2uni_char
stosw
loop @b
jmp .end_copy_name
.ascii2utf8:
cmp edx, 3 ; utf8 encoding
jne .end_copy_name
; convert ascii to utf8
call cp866toUTF8_string
jmp .end_copy_name
.ucs2:
shr ecx, 1 ; ecx/2 - ucs2 chars
cmp edx, 1 ; cp866 encoding
jne .ucs2utf16
; convert ucs2 to ascii
@@:
lodsw
xchg al, ah
call uni2ansi_char
stosb
loop @b
jmp .end_copy_name
.ucs2utf16:
cmp edx, 2 ; utf16 encoding
jne .ucs2utf8
; convert ucs2 to utf16LE
@@:
lodsw
xchg al, ah
stosw
loop @b
jmp .end_copy_name
.ucs2utf8:
cmp edx, 3 ; utf8 encoding
jne .end_copy_name
; convert ucs2 to utf8
mov ebx, ecx
shl ecx, 1
@@:
lodsw
xchg ah, al
call UTF16to8
dec ebx
jnz @b
.end_copy_name:
mov byte[edi], 0
cmp [ebp + ISO9660.type_encoding], 0
jz @f
mov word[edi], 0
@@:
ret