diff --git a/kernel/trunk/blkdev/disk.inc b/kernel/trunk/blkdev/disk.inc index 05ba0b941a..cf649a0b59 100644 --- a/kernel/trunk/blkdev/disk.inc +++ b/kernel/trunk/blkdev/disk.inc @@ -83,6 +83,14 @@ struct DISKFUNC ; Optional, may be NULL. ; unsigned int adjust_cache_size(void* userdata, unsigned int suggested_size); ; Return value: 0 = disable cache, otherwise = used cache size in bytes. + LoadTray dd ? +; This pointer to the function which load and unload tray drive. +; Optional, may be NULL +; int LoadTray(void* userdata, int flags); +; flags: +; 0 - load +; 1 - unload +; Return value: one of DISK_STATUS_* ends ; This structure holds information on a medium. @@ -95,6 +103,8 @@ struct DISKMEDIAINFO ; Size of the sector. Capacity dq ? ; Size of the media in sectors. + LastSessionSector dd ? +; Number last session sectors for CDFS ends ; This structure represents the disk cache. To follow the old implementation, @@ -599,6 +609,7 @@ disk_media_changed: ; 3a. Call the 'querymedia' callback. ; .Flags are set to zero for possible future extensions. lea edx, [esi+DISK.MediaInfo] + and [edx+DISKMEDIAINFO.LastSessionSector], 0 and [edx+DISKMEDIAINFO.Flags], 0 mov al, DISKFUNC.querymedia stdcall disk_call_driver, edx @@ -1282,6 +1293,9 @@ end virtual call xfs_create_partition test eax, eax jnz .success + call iso9660_create_partition + test eax, eax + jnz .success ; 3. No file system has recognized the volume, so just allocate the PARTITION ; structure without extra fields. movi eax, sizeof.PARTITION @@ -1490,6 +1504,7 @@ dyndisk_handler: @@: cmp byte [esi], 0 jnz @f + ; partition info cmp byte [ebx], 1 jz @f cmp byte [ebx], 5 @@ -1502,21 +1517,25 @@ dyndisk_handler: ; was inserted/removed/changed. Otherwise, assume that media status is valid. test byte [edx+DISK.DriverFlags], DISK_NO_INSERT_NOTIFICATION jz .media_accurate + push ecx esi mov esi, edx cmp dword [esp+8], 0 jz .test_no_media cmp [esi+DISK.MediaRefCount], 2 jnz .media_accurate_pop + lea edx, [esi+DISK.MediaInfo] and [edx+DISKMEDIAINFO.Flags], 0 mov al, DISKFUNC.querymedia stdcall disk_call_driver, edx test eax, eax jz .media_accurate_pop + stdcall disk_media_dereference ; drop our reference so that disk_media_changed could close the media stdcall disk_media_changed, esi, 0 and dword [esp+8], 0 ; no media + ;jmp .media_accurate_pop .test_no_media: stdcall disk_media_changed, esi, 1 ; issue fake notification ; if querymedia() inside disk_media_changed returns error, the notification is ignored @@ -1524,9 +1543,11 @@ dyndisk_handler: jz .media_accurate_pop lock inc [esi+DISK.MediaRefCount] mov dword [esp+8], esi + .media_accurate_pop: mov edx, esi pop esi ecx + .media_accurate: pop eax test eax, eax @@ -1688,3 +1709,59 @@ dyndisk_enum_root: xor eax, eax pop edx ; restore register used in file_system_lfn ret + +; void fastcall eject_disk_media(const char* str, uint32_t code); +; for load/eject drive +; ecx -> asciiz string disk name (sd0, usbhd0) +; edx = code command(0 - LoadTray 1-EjectTray) +eject_disk_media: + push esi edx ecx + + mov ecx, disk_list_mutex + call mutex_lock + ; find disk ejected + mov edx, disk_list +.next: + mov edx, [edx] + cmp edx, disk_list + jz .nf + + mov ecx, [edx + DISK.Name] + mov esi, [esp] +@@: + lodsb + test al, al + jz @f + + or al, 0x20 + cmp al, [ecx] + jnz .next + inc ecx + jmp @b +@@: + cmp byte[ecx], al + jnz .next + + mov ecx, disk_list_mutex + call mutex_unlock +; found disk + pop ecx edx esi + + and edx, 1b + mov al, DISKFUNC.LoadTray + stdcall disk_call_driver, edx ; ecx - code command + ret + +.nf: + mov ecx, disk_list_mutex + call mutex_unlock + pop ecx edx esi + ret + +; for disk emulation PARTITION structure +; int32_t find_part(char* esi) esi -> name disk and partition +; return number partition or zero for disk and +;find_part: +; mov ecx, disk_list_mutex +; +; ret diff --git a/kernel/trunk/fs/iso9660.inc b/kernel/trunk/fs/iso9660.inc index c6268140b6..5f2d6b4075 100644 --- a/kernel/trunk/fs/iso9660.inc +++ b/kernel/trunk/fs/iso9660.inc @@ -736,3 +736,1044 @@ cd_compare_name: 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 +