Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 9944 → Rev 9945

/drivers/disk/Tupfile.lua
2,3 → 2,4
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")
/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
/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:
<CODE> virtdisk -d <DISK_NUMBER> </CODE>
 
- Information from disk:
 
<CODE> virtdisk -i <DISK_NUMBER> </CODE>
 
- Add disk image in file system:
 
<CODE> virtdisk -a <IMAGE_PATH> -s <SECTOR_SIZE> -t <IMAGE_TYPE> -f <ACCESS_FLAGS> </CODE>
 
- Input list all virtual disks:
 
<CODE> virtdisk -l </CODE>
 
## List flags:
- <CODE>ro</CODE> - read only access
- <CODE>rw</CODE> - read-write access
 
## List disk image types:
- <CODE>RAW</CODE> - it is used to mount disk images in "raw", "img" and "iso" formats
 
## Exemples command:
<CODE> virtdisk -a /sd0/4/kolibri.img -f ro </CODE>
<CODE> virtdisk -d 3 </CODE>
/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")
/programs/system/virtdisk/parser.inc
0,0 → 1,322
; data for parsing string
param_cmd: dd 0 ;set when for "-a" command
 
; virtdisk -d <DISK_NUMBER>
; virtdisk -i <DISK_NUMBER>
; virtdisk -a <PATH> -s <SECTOR_SIZE> -t <IMAGE_TYPE> -f <FLAGS>
; 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
/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
/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