kolibrios/kernel/trunk/fs/iso9660.inc

1780 lines
46 KiB
PHP
Raw Permalink Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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