diff --git a/drivers/disk/Tupfile.lua b/drivers/disk/Tupfile.lua index 8d3a88b15b..b1ce9d56b1 100644 --- a/drivers/disk/Tupfile.lua +++ b/drivers/disk/Tupfile.lua @@ -2,3 +2,4 @@ if tup.getconfig("NO_FASM") ~= "" then return end ROOT = "../.." tup.include(ROOT .. "/programs/use_fasm.lua") tup.rule("tmpdisk.asm", "fasm %f %o " .. PESTRIP_CMD .. tup.getconfig("KPACK_CMD"), "%B.sys") +tup.rule("virt_disk.asm", "fasm %f %o " .. PESTRIP_CMD .. tup.getconfig("KPACK_CMD"), "%B.sys") \ No newline at end of file diff --git a/drivers/disk/virt_disk.asm b/drivers/disk/virt_disk.asm new file mode 100644 index 0000000000..9b1358b671 --- /dev/null +++ b/drivers/disk/virt_disk.asm @@ -0,0 +1,725 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2023. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; Virtual disk driver for KolibriOS ;; +;; ;; +;; Written by Mikhail Frolov aka Doczom ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DISK_STATUS_OK = 0 ; success +DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable +DISK_STATUS_INVALID_CALL = 1 ; invalid input parameters +DISK_STATUS_NO_MEDIA = 2 ; no media present +DISK_STATUS_END_OF_MEDIA = 3 ; end of media while reading/writing data + +; For all IOCTLs the driver returns one of the following error codes: +NO_ERROR equ 0 +ERROR_INVALID_IOCTL equ 1 ; unknown IOCTL code + +maxPathLength = 1000h + +include '../struct.inc' + +; TODO list: +; add support VDI image + +; Input structures: +Flag: + .Ro = 1b + .Wo = 10b + .RW = 11b + +struct DISK_DEV + next rd 1 + pref rd 1 + SectorCount rd 2 + DiskHandle rd 1 + DiskNumber rd 1 + Flags rd 1 ; 1-ro 2-wo 3-rw + TypeImage rd 1 ; 0-raw 1-vhd 2-vdi 3-imd + SectorSize rd 1 + DiskPath rb maxPathLength +ends +struct IMAGE_ADD_STRUCT + Flags rd 1 ; 1-ro 2-wo 3-rw + TypeImage rd 1 ; 0-raw 1-vhd 2-vdi 3-imd + SectorSize rd 1 + DiskPath rb maxPathLength +ends + +struct DISKMEDIAINFO + Flags dd ? + SectorSize dd ? + Capacity dq ? +ends + + DEBUG = 1 + __DEBUG__ = 1 + __DEBUG_LEVEL__ = 1 ; 1 = verbose, 2 = errors only + +format PE DLL native 0.05 +entry START + +section '.flat' code readable writable executable + +include '../proc32.inc' +include '../peimport.inc' +include '../macros.inc' + +include '../fdo.inc' + +proc START c, state:dword, cmdline:dword + xor eax, eax ; set return value in case we will do nothing + cmp dword [state], 1 + jne .nothing + + mov ecx, disk_list_lock + invoke MutexInit + + DEBUGF 1, "VIRT_DISK: driver loaded\n" + invoke RegService, my_service, service_proc + ret +.nothing: + ret +endp + +; get version +; add disk +; del disk +; get list disks +; get disk info +proc service_proc + push ebx esi edi +; 2. Get parameter from the stack: [esp+16] is the first parameter, +; pointer to IOCTL structure. + mov ebx, [esp + 16] ; edx -> IOCTL + + mov ecx, [ebx + IOCTL.io_code] + test ecx, ecx ; check for SRV_GETVERSION + jnz .add_disk + + cmp [ebx + IOCTL.out_size], 4 + jb .error_ret + mov eax, [ebx + IOCTL.output] + mov dword [eax], 1 ;API_VERSION + xor eax, eax + jmp .return + +.add_disk: + dec ecx ; check for DEV_ADD_DISK + jnz .del_disk + + cmp [ebx + IOCTL.inp_size], sizeof.IMAGE_ADD_STRUCT + jb .error_ret + + cmp [ebx + IOCTL.out_size], 4 + jb .error_ret + + invoke KernelAlloc, sizeof.DISK_DEV + test eax, eax + jz .error_ret + + push eax + mov edi, eax + mov ecx, sizeof.DISK_DEV/4 + xor eax, eax + rep stosd + pop eax + + mov edi, eax + add edi, DISK_DEV.Flags + mov esi, [ebx + IOCTL.input] + mov ecx, sizeof.IMAGE_ADD_STRUCT/4 + rep movsd + + mov esi, eax ;save + + cmp byte[esi + DISK_DEV.DiskPath], '/' + jnz .add_disk.error + + mov ecx, disk_list_lock + invoke MutexLock + + call get_free_num + jnz .add_disk.error2 + mov [esi + DISK_DEV.DiskNumber], eax + mov ecx,[ebx + IOCTL.output] + mov [ecx], eax + + ; init image + mov eax, [esi + DISK_DEV.TypeImage] + cmp eax, image_type.max_num + ja .add_disk.error2 + + call dword[image_type + eax*8] ;esi - DISK_DEV* + test eax, eax + jnz .add_disk.error2 + + ; creating name + push ebp + mov ebp, esp + + mov eax, [esi + DISK_DEV.DiskNumber] + mov edi, esp + dec edi + mov byte[edi], 0 + mov ecx, 10 +@@: + xor edx, edx + div ecx + add edx,'0' + dec edi + mov byte[edi], dl + test eax, eax + jnz @b + + mov esp, edi + push word 'vd' + sub edi, 2 + + ; add disk + mov eax, [esi + DISK_DEV.TypeImage] + invoke DiskAdd, dword[image_type + eax*8 + 4] , \ + edi, esi, 0 + mov [esi + DISK_DEV.DiskHandle], eax + mov esp, ebp + pop ebp + test eax, eax + jz .add_disk.error2 + + invoke DiskMediaChanged, eax, 1 + + ; add in list + mov dword[esi], disk_root_list + mov eax, [disk_root_list + 4] + mov [esi + 4], eax + mov [eax], esi + mov [disk_root_list + 4], esi + inc dword[disk_count] + + mov ecx, disk_list_lock + invoke MutexUnlock + + xor eax, eax + jmp .return + +.add_disk.error2: + mov ecx, disk_list_lock + invoke MutexUnlock + +.add_disk.error: + invoke KernelFree, esi + jmp .error_ret + + +.del_disk: + dec ecx ; check for DEV_DEL_DISK + jnz .get_root_list + + cmp [ebx + IOCTL.inp_size], 4 + jb .error_ret + + mov ecx, [ebx + IOCTL.input] + mov ecx, [ecx] + call get_disk + + test eax, eax + jz .error_ret + + cmp [eax + DISK_DEV.DiskHandle], 0 + jz .error_ret + mov ecx, [eax + DISK_DEV.DiskHandle] + mov [eax + DISK_DEV.DiskHandle], 0 + invoke DiskDel, ecx + + xor eax, eax + jmp .return + +.get_root_list: + dec ecx ; check for DEV_DEL_DISK + jnz .get_disk_info + + cmp [ebx + IOCTL.inp_size], 4*2 ; offset + count + jb .error_ret + mov ecx, [ebx + IOCTL.input] + mov edx, [ecx] ; offset + mov eax, [ecx + 4] ; count + + add edx, eax + cmp edx, [disk_count] + ja .error_ret + + xor edx, edx + imul eax, sizeof.DISK_DEV - 8 + add eax, 4 + cmp [ebx + IOCTL.out_size], eax + jb .error_ret + + mov edi, [ebx + IOCTL.output] + mov eax, [disk_count] + stosd + + mov edx, [ecx] + mov eax, [disk_root_list] +@@: + test edx, edx + jz @f + mov eax, [eax] + dec edx + jmp @b +@@: + mov edx, [ecx + 4] +@@: + test edx, edx + jz @f + mov esi, eax + add esi, 8 + mov ecx, (sizeof.DISK_DEV - 8)/4 + rep movsd + mov eax, [eax] + dec edx + jmp @b +@@: + xor eax, eax + jmp .return + +.get_disk_info: + dec ecx + jnz .error_ret + + cmp [ebx + IOCTL.inp_size], 4 + jb .error_ret + cmp [ebx + IOCTL.out_size], sizeof.DISK_DEV - 8 + jb .error_ret + mov ecx, [ebx + IOCTL.input] + mov ecx, [ecx] + + call get_disk + test eax, eax + jz .error_ret + + mov esi, eax + add esi, 4*2 + mov edi, [ebx + IOCTL.output] + mov ecx, (sizeof.DISK_DEV - 8)/4 + rep movsd + + xor eax, eax + jmp .return + +.error_ret: + mov eax, ERROR_INVALID_IOCTL +.return: + pop edi esi ebx + retn 4 +endp + +; IN: ecx - ptr DISK_DEV +; OUT: ZF - found zF - not found +proc disk_dev_check + push eax + mov eax, disk_root_list +@@: + mov eax, [eax] + cmp eax, disk_root_list + jz .nf + cmp eax, ecx + jnz @b + pop eax + ret +.nf: + test eax, eax + pop eax + ret +endp +; IN: ecx - disk number +; OUT: eax - ptr DISK_DEV +proc get_disk + push ecx + mov ecx, disk_list_lock + invoke MutexLock + pop ecx + + mov eax, disk_root_list +@@: + mov eax, [eax] + cmp eax, disk_root_list + jz .nf + cmp ecx, [eax + DISK_DEV.DiskNumber] + jnz @b + + push eax + mov ecx, disk_list_lock + invoke MutexUnlock + pop eax + ret +.nf: + mov ecx, disk_list_lock + invoke MutexUnlock + + xor eax, eax + ret +endp + +; OUT: eax - number free disk +; Zf - good zf - not found +proc get_free_num + xor eax, eax + mov edx, disk_root_list +@@: + mov edx, [edx] + cmp edx, disk_root_list + jz @f + cmp eax, [edx + DISK_DEV.DiskNumber] + jnz @b + + inc eax + jnz @b + + test edx, edx ; random :) +@@: + ret +endp + +;; IN: ecx - number disk +;; OUT: eax - ptr to DISK_DEV or zero +;proc get_link_disk +; +; push ecx +; mov ecx, disk_list_lock +; invoke MutexLock +; pop ecx +; +; xor eax, eax +; cmp ecx, [disk_array.len] +; jae .end +; +; mov eax, [disk_array] +; mov eax, [edx + ecx*4] +; +;.end: +; push eax +; ; unlock disk list +; mov ecx, disk_list_lock +; invoke MutexUnlock +; pop eax +; ret +;endp +;; IN: esi - ptr to DISK_DEV +;; OUT: eax - offset in array or -1 +;proc add_link_disk +; ; find free item +; mov ecx, [disk_array] +; xor eax, eax +; dec eax +;@@: +; inc eax +; cmp eax, [disk_array.len] +; jae .not_found +; +; cmp dword[ecx + eax*4], 0 +; jnz @b +; +; mov [ecx + eax*4], esi +; ret +; +;.not_found: +; inc dword[disk_array.len] +; ;get new memory +; mov eax,[disk_array.len] +; shl eax, 2 ;*4 +; invoke Kmalloc +; test eax, eax +; jz .err +; ; copy data +; push edi esi +; mov ecx, [disk_array.len] +; mov edi, eax +; mov esi, [disk_array] +; rep movsd +; pop esi edi +; ; del old array +; xchg [disk_array], eax +; invoke Kfree +; mov eax, [disk_array.len] +; ret +;.err: +; dec dword[disk_array.len] +; mov eax, -1 +; ret +;endp +; +;; IN: ecx - offset in array +;proc del_link_disk +; mov edx, ecx +; dec edx +; cmp edx,[disk_array.len] +; jz .last_item +; +; mov edx,[disk_array] +; mov [edx + ecx*4], 0 +; ret +;.last_item: +; dec dword[disk_array.len] +; ;get new memory +; mov eax,[disk_array.len] +; shl eax, 2 ;*4 +; invoke Kmalloc +; test eax, eax +; jz .err +; ; copy data +; push edi esi +; mov ecx, [disk_array.len] +; mov edi, eax +; mov esi, [disk_array] +; rep movsd +; pop esi edi +; ; del old array +; xchg [disk_array], eax +; invoke Kfree +; ret +;.err: +; inc dword[disk_array.len] +; mov eax, -1 +; ret +;endp + +; RAW IMAGE DISK FUNCTIONS +proc raw_disk_close stdcall, pdata + ; del item list + mov ecx, disk_list_lock + invoke MutexLock + + mov ecx, [pdata] + mov eax, [ecx] ; eax = next + mov edx, [ecx + 4] ; edx = prev + mov [eax + 4], edx ; [next.prev] = prev + mov [edx], eax ; [prev.next] = next + + dec dword[disk_count] + + mov ecx, disk_list_lock + invoke MutexUnlock + + invoke KernelFree, [pdata] + DEBUGF 1, "VIRT_DISK: disk deleted\n" + ret +endp + +proc disk_querymedia stdcall, pdata, mediainfo + mov eax, [mediainfo] + mov edx, [pdata] + mov [eax + DISKMEDIAINFO.Flags], 0 + mov ecx, [edx + DISK_DEV.SectorSize] + mov [eax + DISKMEDIAINFO.SectorSize], ecx + mov ecx, [edx + DISK_DEV.SectorCount] + mov dword[eax + DISKMEDIAINFO.Capacity], ecx + mov ecx, [edx + DISK_DEV.SectorCount + 4] + mov dword[eax + DISKMEDIAINFO.Capacity + 4], ecx + xor eax, eax + ret +endp + +proc raw_disk_rd stdcall pdata: dword,\ + buffer: dword,\ + startsector: qword,\ + numsectors_ptr:dword + + mov ecx, [pdata] + test [ecx + DISK_DEV.Flags], Flag.Ro + jz .no_support + + pusha + lea eax,[ecx + DISK_DEV.DiskPath] + push eax + dec esp + mov byte[esp], 0 + push dword[buffer] + + mov eax, [numsectors_ptr] + mov eax, [eax] + mul dword[ecx + DISK_DEV.SectorSize] + push eax + ; get offset for startsector + mov eax, dword[startsector] + xor edx, edx + mul dword[ecx + DISK_DEV.SectorSize] + push edx + push eax + mov eax, dword[startsector + 4] + mul dword[ecx + DISK_DEV.SectorSize] + add [esp + 4], eax + push dword 0 ;read file + + mov ebx, esp + invoke FS_Service + push eax + mov ecx, [pdata] + mov eax, ebx + xor edx, edx + div dword[ecx + DISK_DEV.SectorSize] + mov edx, [numsectors_ptr] + mov [edx], eax + pop eax + + add esp, 6*4+1 ; size FS struct + test eax, eax + popa + jz @f + mov eax, 1 + ret +@@: + xor eax, eax + ret +.no_support: + mov eax, DISK_STATUS_GENERAL_ERROR + ret +endp + + +proc raw_disk_wr stdcall pdata: dword,\ + buffer: dword,\ + startsector: qword,\ + numsectors_ptr:dword + + mov ecx, [pdata] + test [ecx + DISK_DEV.Flags], Flag.Wo + jz .no_support + + pusha + lea eax,[ecx + DISK_DEV.DiskPath] + push eax + dec esp + mov byte[esp],0 + push dword[buffer] + + mov eax, [numsectors_ptr] + mov eax, [eax] + mul dword[ecx + DISK_DEV.SectorSize] + push eax + ; get offset for startsector + mov eax, dword[startsector] + xor edx, edx + mul dword[ecx + DISK_DEV.SectorSize] + push edx + push eax + xor edx, edx + mov eax, dword[startsector + 4] + mul dword[ecx + DISK_DEV.SectorSize] + add [esp + 4], eax + push dword 3 ; write file + mov ebx, esp + invoke FS_Service + + push eax + mov ecx, [pdata] + mov eax, ebx + xor edx, edx + div dword[ecx + DISK_DEV.SectorSize] + mov edx, [numsectors_ptr] + mov [edx], eax + pop eax + + add esp, 6*4+1 ; size FS struct + test eax, eax + popa + jz @f + mov eax, 1 + ret +@@: + xor eax, eax + ret + +.no_support: + mov eax, DISK_STATUS_GENERAL_ERROR + ret +endp + +disk_root_list: + dd disk_root_list + dd disk_root_list +disk_count: dd 0 +disk_list_lock: MUTEX + +image_type: + ; init function, table disk function + dd raw_image_init, raw_disk_functions + ; vdi +.max_num = ($ - image_type - 8) / 8; 8 - item size + +align 4 +; esi - ptr to DISK_DEV +;WARNING: raw image size >=2tb not supported. + +proc raw_image_init + sub esp, 40 ; for file_info + mov ecx, esp + + pusha + lea eax,[esi + DISK_DEV.DiskPath] + push eax + dec esp + mov byte[esp],0 + push ecx + xor eax, eax + push eax eax eax + push dword 5 + + mov ebx, esp + invoke FS_Service + add esp, 6*4+1 + test eax, eax + popa + lea esp,[esp + 40] + jnz .err + + ; WARNING: Not working with stack, destroys the structure! + mov eax, [ecx + 32] + mov edx, [ecx + 36] + test eax, eax + jz .err + + div dword[esi + DISK_DEV.SectorSize] ; undefined exeption + mov [esi + DISK_DEV.SectorCount], eax + mov [esi + DISK_DEV.SectorCount + 4], 0 + ; END WARNING + + xor eax, eax + ret +.err: + or eax, -1 + ret +endp + +align 4 +raw_disk_functions: + dd .size + dd raw_disk_close + dd 0 ; no need in .closemedia + dd disk_querymedia + dd raw_disk_rd + dd raw_disk_wr + dd 0 ; no need in .flush + dd disk_adjust_cache_size +.size = $ - raw_disk_functions + +proc disk_adjust_cache_size + virtual at esp+4 + .userdata dd ? + .suggested_size dd ? + end virtual + xor eax, eax + retn 8 +endp + +my_service db 'VIRT_DISK',0 + +data fixups +end data + +include_debug_strings \ No newline at end of file diff --git a/programs/system/virtdisk/README.md b/programs/system/virtdisk/README.md new file mode 100644 index 0000000000..bd763bdf69 --- /dev/null +++ b/programs/system/virtdisk/README.md @@ -0,0 +1,34 @@ +# VIRT_DISK +Driver for mounting RAW disk images in KolibriOS. + +To demonstrate the operation of the driver, the virtdisk program was written. Program allows you to add, delete and view virtual disks. +![foto](https://github.com/Doczom/VIRT_DISK/blob/main/utils/scr_1.png) + +## List of virtdisk arguments: + - Delete command: + + virtdisk -d + + - Information from disk: + + virtdisk -i + + - Add disk image in file system: + + virtdisk -a -s -t -f + + - Input list all virtual disks: + + virtdisk -l + +## List flags: + - ro - read only access + - rw - read-write access + +## List disk image types: + - RAW - it is used to mount disk images in "raw", "img" and "iso" formats + +## Exemples command: + virtdisk -a /sd0/4/kolibri.img -f ro + + virtdisk -d 3 diff --git a/programs/system/virtdisk/Tupfile.lua b/programs/system/virtdisk/Tupfile.lua new file mode 100644 index 0000000000..2ffe0e070f --- /dev/null +++ b/programs/system/virtdisk/Tupfile.lua @@ -0,0 +1,2 @@ +if tup.getconfig("NO_FASM") ~= "" then return end +tup.rule("virtdisk.asm", "fasm %f %o " .. tup.getconfig("KPACK_CMD"), "virtdisk") diff --git a/programs/system/virtdisk/parser.inc b/programs/system/virtdisk/parser.inc new file mode 100644 index 0000000000..00bec8c86f --- /dev/null +++ b/programs/system/virtdisk/parser.inc @@ -0,0 +1,322 @@ +; data for parsing string +param_cmd: dd 0 ;set when for "-a" command + +; virtdisk -d +; virtdisk -i +; virtdisk -a -s -t -f +; virtdisk -l +parse_cmd: + mov edi, PATH + ; find string length + xor al, al + mov ecx, 4096 + repne scasb + + mov ecx, edi + sub ecx, PATH + mov edi, PATH +.still: + mov al, ' ' + repz scasb + + test ecx, ecx + jz .end_parser + + dec edi + or word[edi], 0x2020 ; яхЁхтюфшь т эшцэшщ ЁхушёЄЁ + ; -a -d -i -l -s -t -f + + cmp word[edi], '-a' + jnz @f + ;add virt disk + mov dword[param_cmd],-1 + + add edi, 3 + sub ecx, 2 + js ERROR_EXIT ; error not found path + + mov edx, add_disk.file + call .copy_str + or dword[edx -4], 0x20202020 + mov dword[add_disk.size], 512 + cmp dword[edx -4], '.iso' + jnz .still + mov dword[add_disk.size], 2048 + + jmp .still +@@: + cmp word[edi], '-d' + jnz @f + + add edi, 3 + sub ecx, 2 + js ERROR_EXIT ; error not found path + + call .get_number + mov [disk_num],eax + + pusha + mov al, 68 + mov bl, 17 + mov ecx, ioctl_del_disk + int 0x40 + + push str_command_successfully + call _sc_puts + popa + + jmp .still +@@: + cmp word[edi], '-i' + jnz .no_disk_info + ; write info + add edi, 3 + sub ecx, 2 + js ERROR_EXIT ; error not found path + ; get disk number + call .get_number + mov [disk_num],eax + + pusha + mov al, 68 + mov bl, 17 + mov ecx, ioctl_info_disk + int 0x40 + + call write_disk_info + popa + jmp .still + +.no_disk_info: + cmp word[edi], '-l' + jnz .no_disk_list + ; write list disks + add edi, 2 + sub ecx, 1 + pusha + + mov al, 68 + mov bl, 17 + mov ecx, ioctl_count_disk + int 0x40 + test eax, eax + jnz ERROR_EXIT + + push str_header_disk_list + call _sc_puts + + mov ecx, ioctl_list_disk.count + mov eax, 68 + mov bl, 12 + imul ecx, sizeof.info_buffer + add ecx, 4 + mov [ioctl_list_disk.size_buffer], ecx + int 0x40 + test eax, eax + jz ERROR_EXIT + + mov [ioctl_list_disk.buffer], eax + mov esi, eax + mov edi, eax + add esi, 4 + + mov al, 68 + mov bl, 17 + mov ecx, ioctl_list_disk + int 0x40 + test eax, eax + jnz ERROR_EXIT + + cmp dword[edi], 0 + jz .end_list +.next_item_list: + + ; num2str + push dword 10 + mov ecx, esp + mov eax, [esi + info_buffer.disk_num - info_buffer] +@@: + xor edx, edx + div dword[esp] + dec ecx + add dl, '0' + mov byte[ecx], dl + test eax, eax + jnz @b + + mov edx, str_input_disk_number + 1 + mov dword[edx], ' ' +@@: + mov al, byte[ecx] + mov byte[edx], al + inc edx + inc ecx + cmp ecx, esp + jnz @b + ;------- + mov ecx, esp + mov eax, [esi + info_buffer.sector_size - info_buffer] +@@: + xor edx, edx + div dword[esp] + dec ecx + add dl, '0' + mov byte[ecx], dl + test eax, eax + jnz @b + + mov edx, str_input_disk_sector + mov dword[edx], ' ' +@@: + mov al, byte[ecx] + mov byte[edx], al + inc edx + inc ecx + cmp ecx, esp + jnz @b + ;------- + add esp, 4 + ; flags + mov dword[str_input_disk_flags], ' ' + cmp dword[esi + info_buffer.flags - info_buffer], 1b + jnz @f + mov word[str_input_disk_flags], 'ro' +@@: + cmp dword[esi + info_buffer.flags - info_buffer], 11b + jnz @f + mov word[str_input_disk_flags], 'rw' +@@: + ;------- + pusha + add esi, info_buffer.path - info_buffer + push esi + push str_input_disk_number + call _sc_puts + call _sc_puts + push str_newline + call _sc_puts + popa + + add esi, sizeof.info_buffer + dec dword[edi] + jnz .next_item_list +.end_list: + + mov eax, 68 + mov ebx, 13 + mov ecx, edi + int 0x40 + + popa + jmp .still +.no_disk_list: + cmp dword[param_cmd],0 + jz .no_cmd + + cmp word[edi], '-s' + jnz .no_sector_size + ; set sector size for -a command + add edi, 3 + sub ecx, 2 + js ERROR_EXIT ; error + ; get number + call .get_number + mov [add_disk.size], eax + jmp .still +.no_sector_size: + cmp word[edi], '-t' + jnz .no_disk_type + ; set image type for -a command + add edi, 3+3 + sub ecx, 2+3 + js ERROR_EXIT ; error + + or dword[edi - 4], 0x20202020 + cmp dword[edi - 4], ' raw' + jnz .still + ; TODO!!! + mov dword[add_disk.type], 0 + jmp .still +.no_disk_type: + cmp word[edi], '-f' + jnz .no_cmd + ; set flags for -a command + add edi, 3+2 + sub ecx, 2+2 + js ERROR_EXIT ; error + + or word[edi - 2], 0x2020 + cmp word[edi - 2], 'ro' + jnz @f + mov dword[add_disk.flags], 1b + +@@: cmp word[edi - 2], 'rw' + jnz .still + mov dword[add_disk.flags], 11b + jmp .still +.no_cmd: + inc edi + jmp .still +.end_parser: + ret + +.get_str: + push edi + inc dword[esp] + mov al, '"' + cmp byte[edi], al + jz @f + dec dword[esp] + mov al, ' ' + dec edi +@@: + inc edi + repne scasb + and byte[edi - 1], 0 + pop eax + ret + +; edx - buffer +.copy_str: + mov al, ' ' + cmp byte[edi], '"' + jnz @f + mov al, '"' + inc edi + dec ecx +@@: + mov ah, byte[edi] + test ah, ah + jz @f + cmp ah, al + jz @f + mov byte[edx], ah + inc edx + inc edi + dec ecx + jmp @b +@@: + mov byte[edx], 0 + ret + +.get_number: + xor eax, eax +@@: + movzx edx, byte[edi] + test edx, edx + jz @f + cmp dl, ' ' + jz @f + sub dl, '0' + js ERROR_EXIT + + cmp dl, 9 + ja ERROR_EXIT + + imul eax, 10 + add eax, edx + dec ecx + inc edi + jmp @b +@@: + ret \ No newline at end of file diff --git a/programs/system/virtdisk/shell.inc b/programs/system/virtdisk/shell.inc new file mode 100644 index 0000000000..6f2fa1eaff --- /dev/null +++ b/programs/system/virtdisk/shell.inc @@ -0,0 +1,300 @@ + + +SC_OK = 0 +SC_EXIT = 1 +SC_PUTC = 2 +SC_PUTS = 3 +SC_GETC = 4 +SC_GETS = 5 +SC_CLS = 6 +SC_PID = 7 +SC_PING = 8 + +SHM_WRITE = 0x01 +SHM_OPEN_ALWAYS = 0x04 + +;============================ + +align 4 +sc_name rb 64 +sc_pid dd 0 +sc_buffer dd 0 +sc_process dd 0 + +;============================ + +if used _sc_pid2name +align 4 +_sc_pid2name: + + push esp + push ebx + + xor ecx, ecx + mov eax, [sc_pid] + mov ebx, 10 +@@: + xor edx, edx + div ebx + push edx + inc ecx + test eax, eax + jnz @b + +mov edi, sc_name + +@@: + pop eax + add al, '0' + stosb + loop @b + + + mov al, '-' + stosb + mov al, 'S' + stosb + mov al, 'H' + stosb + mov al, 'E' + stosb + mov al, 'L' + stosb + mov al, 'L' + stosb + mov al, 0 + stosb + + + pop ebx + pop esp + + ret +end if + +;============================ + +if used _sc_init +align 4 +; void __stdcall sc_init(); +_sc_init: + + push esp + push ebx + + mov eax, 68 + mov ebx, 11 + int 0x40 + + mov eax, 68 ; выделить память + mov ebx, 12 + mov ecx, 1024 + int 0x40 + + mov [sc_process], eax + + mov eax, 9 ; получить информацию о текущем процессе + mov ebx, [sc_process] + mov ecx, -1 + int 0x40 + + mov dword eax, [ebx+30] ; получаем PID текщего процесса + mov [sc_pid], eax + + mov eax, 68 ; освободить память + mov ebx, 13 + mov ecx, [sc_process] + int 0x40 + + call _sc_pid2name + + mov eax, 68 ; открыть именованную область + mov ebx, 22 + mov dword ecx, sc_name + mov edx, 4096 + mov esi, SHM_OPEN_ALWAYS or SHM_WRITE + int 0x40 + + mov [sc_buffer], eax + + pop ebx + pop esp + + ret +end if + +;============================ + +if used _sc_puts +align 4 +; void __stdcall sc_puts(char *str); +_sc_puts: + + push esp + push ebx + + mov esi, [esp+12] + mov edi, [sc_buffer] + mov al, SC_PUTS + stosb + +@@: + lodsb + stosb + test al, al + jnz @b + + mov ebx, [sc_buffer] + +@@: + mov byte dl, [ebx] + test dl, dl + jz @f + push ebx + mov eax, 5 + mov ebx, 5 + int 0x40 + pop ebx + jmp @b + +@@: + + pop ebx + pop esp + ret 4 +end if + +;============================ + +if used _sc_exit +align 4 +; void __stdcall sc_exit(); +_sc_exit: + push ebx + push esp + + mov ebx, [sc_buffer] + mov byte [ebx], SC_EXIT + +@@: + mov byte dl, [ebx] + test dl, dl + jz @f + push ebx + mov eax, 5 + mov ebx, 5 + int 0x40 + pop ebx + jmp @b + +@@: + mov eax, 68 ;закрыть именованную область + mov ebx, 23 + mov dword ecx, sc_name + int 0x40 + + pop esp + pop ebx + ret +end if + + +;============================ + +if used _sc_gets +align 4 +; void __stdcall sc_gets(char *str); +_sc_gets: + + push esp + push ebx + + mov edi, [esp+12] + + mov ebx, [sc_buffer] + mov byte [ebx], SC_GETS + +@@: + mov byte dl, [ebx] + test dl, dl + jz @f + push ebx + mov eax, 5 + mov ebx, 5 + int 0x40 + pop ebx + jmp @b + +@@: + + + mov esi, [sc_buffer] + inc esi + +@@: + lodsb + stosb + test al, al + jnz @b + + pop ebx + pop esp + ret 4 +end if + +;============================ + +if used _sc_pid +_sc_pid: +;int __stdcall sc_pid (void); + push ebx ecx + + mov ecx, [sc_buffer] + mov byte [ecx], SC_PID + +@@: + mov eax, 5 + mov ebx, 5 + int 0x40 + + cmp byte [ecx], 0 + je @f + call _sc_ping + test eax, eax + jnz .err + +@@: + mov eax, [ecx+1] + pop ecx ebx + ret + +.err: + pop ecx ebx + xor eax, eax + dec eax + ret +end if + +;============================ + +if used _sc_ping +_sc_ping: +;int __stdcall sc_ping (void); + push ebx ecx + + mov ecx, [sc_buffer] + mov byte [ecx], SC_PING + + mov eax, 5 + mov ebx, 200 + int 0x40 + + xor eax, eax + cmp byte [ecx], 0 + je @f + dec eax + +@@: + pop ecx ebx + ret +end if diff --git a/programs/system/virtdisk/virtdisk.asm b/programs/system/virtdisk/virtdisk.asm new file mode 100644 index 0000000000..cd983cde99 --- /dev/null +++ b/programs/system/virtdisk/virtdisk.asm @@ -0,0 +1,173 @@ +;-----------------------------------------------------------------------------; +; Copyright (C) 2023, Mikhail Frolov aka Doczom . All rights reserved. ; +; Distributed under terms of the GNU General Public License ; +; ; +; Demo program for the VIRT_DISK driver. ; +; ; +; GNU GENERAL PUBLIC LICENSE ; +; Version 2, June 1991 ; +; ; +;-----------------------------------------------------------------------------; +format binary as "" + use32 + org 0 + db 'MENUET01' + dd 1, START, I_END, MEM, STACKTOP, PATH, 0 + +include 'parser.inc' +include 'shell.inc' +START: + call _sc_init + + mov al, 68 + mov bl, 16 + mov ecx, drv_name + int 0x40 + mov [ioctl_add_disk.hand], eax + mov [ioctl_del_disk.hand], eax + mov [ioctl_info_disk.hand], eax + mov [ioctl_list_disk.hand], eax + mov [ioctl_count_disk.hand], eax + test eax, eax + jz .end + + cmp byte[PATH], 0 + jz .end + + call parse_cmd + + cmp dword[param_cmd],0 + jz .end + + mov al, 68 + mov bl, 17 + mov ecx, ioctl_add_disk + int 0x40 + test eax, eax + jnz @f + push str_command_successfully + call _sc_puts + jmp .end +@@: + push str_error + call _sc_puts +.end: + call _sc_exit + mov eax,-1 + int 0x40 +ERROR_EXIT: + push str_runtime_err + call _sc_puts + + call _sc_exit + mov eax,-1 + int 0x40 +write_disk_info: + pusha + push str_disk_info.path + call _sc_puts + + push info_buffer.path + call _sc_puts + + push str_newline + call _sc_puts + popa + ret + + +I_END: +drv_name: db 'VIRT_DISK',0 + +; messages +str_runtime_err: + db 'Runtime error', 13, 10, 0 +str_command_successfully: + db 'Command successfully', 13, 10, 0 +str_header_disk_list: + db ' disk | sector | flags | file', 13, 10 + db '-------|--------|-------|---------------------',13, 10, 0 +str_input_disk_number: + db ' | ' ; ,0 +str_input_disk_sector: + db ' | ';,0 +str_input_disk_flags: + db ' | ',0 +str_error: + db 'Error',0 +str_disk_info: +.num: db 'Disk number: ',0 +;.type: db 'Type: ', 0 +;.sector_size: +; db 'Sector size: ', 0 +.path: db 'File: ', 0 +str_newline: + db ' ', 13, 10, 0 + +ioctl_count_disk: +.hand: dd 0, 3 ;iocode + dd .get_count_disk, 8 + dd ioctl_list_disk.count, 4 +.get_count_disk: + dd 0, 0 + +ioctl_list_disk: +.hand: dd 0, 3 ;iocode + dd .inp, 8 +.buffer: + dd 0 +.size_buffer: + dd 0 +.inp: + dd 0 +.count: dd 0 + +ioctl_info_disk: +.hand: dd 0, 4 ;iocode + dd disk_num, 4 + dd info_buffer, sizeof.info_buffer +ioctl_del_disk: +.hand: dd 0, 2 ;iocode + dd disk_num, 4 + dd 0, 0 +ioctl_add_disk: +.hand: dd 0, 1 ;iocode + dd add_disk, add_disk.end - add_disk + dd disk_num, 4 + +disk_num: rd 0 +add_disk: +.flags: dd 11b ;rw +.type: dd 0 ; TypeImage 0 - RAW +.size: dd 512 +.file: rb 4096 +.end: + +PATH: rb 4096 + +info_buffer: +.sector_count: rd 2 +.disk_hand: rd 1 +.disk_num: rd 1 +.flags: rd 1 +.type: rd 1 +.sector_size: rd 1 +.path: rb 4096 +sizeof.info_buffer = $ - info_buffer + + rb 4096 +STACKTOP: +MEM: +; EXAMPLE COMMANDS: +; virtdisk -f/sd0/4/kolibri.img -s512 +; virtdisk -f/sd0/4/kolibri.img +; virtdisk -f/sd0/4/kolibri.iso -s2048 +; default sector size = 512 for all disk +; 2048 for ISO disk + +;struct IMAGE_ADD_STRUCT +; Flags rd 1 ; 1-ro 2-wo 3-rw +; TypeImage rd 1 ; 0-raw 1-vhd 2-vdi 3-imd +; SectorSize rd 1 +; DiskPath rb maxPathLength +;ends \ No newline at end of file