1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;; Copyright (C) KolibriOS team 2023. All rights reserved. ;;
4 ;; Distributed under terms of the GNU General Public License ;;
6 ;; Virtual disk driver for KolibriOS ;;
8 ;; Written by Mikhail Frolov aka Doczom ;;
10 ;; GNU GENERAL PUBLIC LICENSE ;;
11 ;; Version 2, June 1991 ;;
13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14 DISK_STATUS_OK
= 0 ; success
15 DISK_STATUS_GENERAL_ERROR
= -1; if no other code is suitable
16 DISK_STATUS_INVALID_CALL
= 1 ; invalid input parameters
17 DISK_STATUS_NO_MEDIA
= 2 ; no media present
18 DISK_STATUS_END_OF_MEDIA
= 3 ; end of media while reading/writing data
20 ; For all IOCTLs the driver returns one of the following error codes:
22 ERROR_INVALID_IOCTL
equ 1 ; unknown IOCTL code
26 include '../struct.inc'
29 ; add support VDI image
43 Flags rd
1 ; 1-ro 2-wo 3-rw
44 TypeImage rd
1 ; 0-raw 1-vhd 2-vdi 3-imd
46 DiskPath rb maxPathLength
48 struct IMAGE_ADD_STRUCT
49 Flags rd
1 ; 1-ro 2-wo 3-rw
50 TypeImage rd
1 ; 0-raw 1-vhd 2-vdi 3-imd
52 DiskPath rb maxPathLength
63 __DEBUG_LEVEL__
= 1 ; 1 = verbose, 2 = errors only
65 format PE DLL native
0.05
68 section '.flat' code readable writable executable
70 include '../proc32.inc'
71 include '../peimport.inc'
72 include '../macros.inc'
76 proc START c
, state:dword, cmdline:dword
77 xor eax, eax ; set return value in case we will do nothing
81 mov ecx, disk_list_lock
84 DEBUGF
1, "VIRT_DISK: driver loaded\n"
85 invoke RegService
, my_service
, service_proc
98 ; 2. Get parameter from the stack: [esp+16] is the first parameter,
99 ; pointer to IOCTL structure.
100 mov ebx, [esp + 16] ; edx -> IOCTL
102 mov ecx, [ebx + IOCTL.io_code
]
103 test ecx, ecx ; check for SRV_GETVERSION
106 cmp [ebx + IOCTL.out_size
], 4
108 mov eax, [ebx + IOCTL.output
]
109 mov dword [eax], 1 ;API_VERSION
114 dec ecx ; check for DEV_ADD_DISK
117 cmp [ebx + IOCTL.inp_size
], sizeof.IMAGE_ADD_STRUCT
120 cmp [ebx + IOCTL.out_size
], 4
123 invoke KernelAlloc
, sizeof.DISK_DEV
129 mov ecx, sizeof.DISK_DEV
/4
135 add edi, DISK_DEV.Flags
136 mov esi, [ebx + IOCTL.input
]
137 mov ecx, sizeof.IMAGE_ADD_STRUCT
/4
142 cmp byte[esi + DISK_DEV.DiskPath
], '/'
145 mov ecx, disk_list_lock
150 mov [esi + DISK_DEV.DiskNumber
], eax
151 mov ecx,[ebx + IOCTL.output
]
155 mov eax, [esi + DISK_DEV.TypeImage
]
156 cmp eax, image_type.max_num
159 call dword[image_type
+ eax*8] ;esi - DISK_DEV*
167 mov eax, [esi + DISK_DEV.DiskNumber
]
186 mov eax, [esi + DISK_DEV.TypeImage
]
187 invoke DiskAdd
, dword[image_type
+ eax*8 + 4] , \
189 mov [esi + DISK_DEV.DiskHandle
], eax
195 invoke DiskMediaChanged
, eax, 1
198 mov dword[esi], disk_root_list
199 mov eax, [disk_root_list
+ 4]
202 mov [disk_root_list
+ 4], esi
203 inc dword[disk_count
]
205 mov ecx, disk_list_lock
212 mov ecx, disk_list_lock
216 invoke KernelFree
, esi
221 dec ecx ; check for DEV_DEL_DISK
224 cmp [ebx + IOCTL.inp_size
], 4
227 mov ecx, [ebx + IOCTL.input
]
234 cmp [eax + DISK_DEV.DiskHandle
], 0
236 mov ecx, [eax + DISK_DEV.DiskHandle
]
237 mov [eax + DISK_DEV.DiskHandle
], 0
244 dec ecx ; check for DEV_DEL_DISK
247 cmp [ebx + IOCTL.inp_size
], 4*2 ; offset + count
249 mov ecx, [ebx + IOCTL.input
]
250 mov edx, [ecx] ; offset
251 mov eax, [ecx + 4] ; count
254 cmp edx, [disk_count
]
258 imul
eax, sizeof.DISK_DEV
- 8
260 cmp [ebx + IOCTL.out_size
], eax
263 mov edi, [ebx + IOCTL.output
]
264 mov eax, [disk_count
]
268 mov eax, [disk_root_list
]
282 mov ecx, (sizeof.DISK_DEV
- 8)/4
295 cmp [ebx + IOCTL.inp_size
], 4
297 cmp [ebx + IOCTL.out_size
], sizeof.DISK_DEV
- 8
299 mov ecx, [ebx + IOCTL.input
]
308 mov edi, [ebx + IOCTL.output
]
309 mov ecx, (sizeof.DISK_DEV
- 8)/4
316 mov eax, ERROR_INVALID_IOCTL
322 ; IN: ecx - ptr DISK_DEV
323 ; OUT: ZF - found zF - not found
326 mov eax, disk_root_list
329 cmp eax, disk_root_list
340 ; IN: ecx - disk number
341 ; OUT: eax - ptr DISK_DEV
344 mov ecx, disk_list_lock
348 mov eax, disk_root_list
351 cmp eax, disk_root_list
353 cmp ecx, [eax + DISK_DEV.DiskNumber
]
357 mov ecx, disk_list_lock
362 mov ecx, disk_list_lock
369 ; OUT: eax - number free disk
370 ; Zf - good zf - not found
373 mov edx, disk_root_list
376 cmp edx, disk_root_list
378 cmp eax, [edx + DISK_DEV.DiskNumber
]
384 test edx, edx ; random :)
389 ;; IN: ecx - number disk
390 ;; OUT: eax - ptr to DISK_DEV or zero
394 ; mov ecx, disk_list_lock
399 ; cmp ecx, [disk_array.len]
402 ; mov eax, [disk_array]
403 ; mov eax, [edx + ecx*4]
408 ; mov ecx, disk_list_lock
413 ;; IN: esi - ptr to DISK_DEV
414 ;; OUT: eax - offset in array or -1
417 ; mov ecx, [disk_array]
422 ; cmp eax, [disk_array.len]
425 ; cmp dword[ecx + eax*4], 0
428 ; mov [ecx + eax*4], esi
432 ; inc dword[disk_array.len]
434 ; mov eax,[disk_array.len]
441 ; mov ecx, [disk_array.len]
443 ; mov esi, [disk_array]
447 ; xchg [disk_array], eax
449 ; mov eax, [disk_array.len]
452 ; dec dword[disk_array.len]
457 ;; IN: ecx - offset in array
461 ; cmp edx,[disk_array.len]
464 ; mov edx,[disk_array]
465 ; mov [edx + ecx*4], 0
468 ; dec dword[disk_array.len]
470 ; mov eax,[disk_array.len]
477 ; mov ecx, [disk_array.len]
479 ; mov esi, [disk_array]
483 ; xchg [disk_array], eax
487 ; inc dword[disk_array.len]
492 ; RAW IMAGE DISK FUNCTIONS
493 proc raw_disk_close stdcall
, pdata
495 mov ecx, disk_list_lock
499 mov eax, [ecx] ; eax = next
500 mov edx, [ecx + 4] ; edx = prev
501 mov [eax + 4], edx ; [next.prev] = prev
502 mov [edx], eax ; [prev.next] = next
504 dec dword[disk_count
]
506 mov ecx, disk_list_lock
509 invoke KernelFree
, [pdata
]
510 DEBUGF
1, "VIRT_DISK: disk deleted\n"
514 proc disk_querymedia stdcall
, pdata
, mediainfo
517 mov [eax + DISKMEDIAINFO.Flags
], 0
518 mov ecx, [edx + DISK_DEV.SectorSize
]
519 mov [eax + DISKMEDIAINFO.SectorSize
], ecx
520 mov ecx, [edx + DISK_DEV.SectorCount
]
521 mov dword[eax + DISKMEDIAINFO.Capacity
], ecx
522 mov ecx, [edx + DISK_DEV.SectorCount
+ 4]
523 mov dword[eax + DISKMEDIAINFO.Capacity
+ 4], ecx
528 proc raw_disk_rd stdcall
pdata: dword,\
534 test [ecx + DISK_DEV.Flags
], Flag.Ro
538 lea eax,[ecx + DISK_DEV.DiskPath
]
544 mov eax, [numsectors_ptr
]
546 mul dword[ecx + DISK_DEV.SectorSize
]
548 ; get offset for startsector
549 mov eax, dword[startsector
]
551 mul dword[ecx + DISK_DEV.SectorSize
]
554 mov eax, dword[startsector
+ 4]
555 mul dword[ecx + DISK_DEV.SectorSize
]
557 push dword 0 ;read file
565 div dword[ecx + DISK_DEV.SectorSize
]
566 mov edx, [numsectors_ptr
]
570 add esp, 6*4+1 ; size FS struct
580 mov eax, DISK_STATUS_GENERAL_ERROR
585 proc raw_disk_wr stdcall
pdata: dword,\
591 test [ecx + DISK_DEV.Flags
], Flag.Wo
595 lea eax,[ecx + DISK_DEV.DiskPath
]
601 mov eax, [numsectors_ptr
]
603 mul dword[ecx + DISK_DEV.SectorSize
]
605 ; get offset for startsector
606 mov eax, dword[startsector
]
608 mul dword[ecx + DISK_DEV.SectorSize
]
612 mov eax, dword[startsector
+ 4]
613 mul dword[ecx + DISK_DEV.SectorSize
]
615 push dword 3 ; write file
623 div dword[ecx + DISK_DEV.SectorSize
]
624 mov edx, [numsectors_ptr
]
628 add esp, 6*4+1 ; size FS struct
639 mov eax, DISK_STATUS_GENERAL_ERROR
647 disk_list_lock: MUTEX
650 ; init function, table disk function
651 dd raw_image_init
, raw_disk_functions
653 .max_num
= ($
- image_type
- 8) / 8; 8 - item size
656 ; esi - ptr to DISK_DEV
657 ;WARNING: raw image size >=2tb not supported.
660 sub esp, 40 ; for file_info
664 lea eax,[esi + DISK_DEV.DiskPath
]
681 ; WARNING: Not working with stack, destroys the structure!
687 div dword[esi + DISK_DEV.SectorSize
] ; undefined exeption
688 mov [esi + DISK_DEV.SectorCount
], eax
689 mov [esi + DISK_DEV.SectorCount
+ 4], 0
703 dd 0 ; no need in .closemedia
707 dd 0 ; no need in .flush
708 dd disk_adjust_cache_size
709 .
size = $
- raw_disk_functions
711 proc disk_adjust_cache_size
720 my_service
db 'VIRT_DISK',0
725 include_debug_strings