;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; BSD 3-Clause License ;; ;; ;; ;; Copyright (C) 2022, Michael Frolov aka Doczom ;; ;; All rights reserved. ;; ;; ;; ;; Device subsystem from kernel Kolibri OS. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; struct DEVICE next dd 0 dd 0 prev dd 0 dd 0 type dd 0 dd 0 func dd 0 ; pointer to export function fastcall int func(void data, DEV_IOCTL* iocl) dd 0 subtype dd 0 ; real type devise dd 0 dd 0 dd 0 ; ну чтоб точно хватило места на тип magic dd 0;'DEV_' size dd sizeof.DEVICE func_k dd 0 ; pointer to export function for kernel fastcall int func(void data, DEV_IOCTL* iocl) dd 0 ; fastcall void exit(void data) exit dd 0 ; pointer to function clear and destroy this device dd 0 data dd 0 ; data for functions for this device dd 0 ends ; Subtype format ; ; offset 0x00 ; 0xYYRRRRXX ; YY - bus protool ; 0 - old dev ; 1 - pci dev ; 2 - acpi dev ; 3 - usb dev ; 4 - virtual dev ; XX - подтип, например для pci тут будет по сути класс, для юсб тоже, для acpi не знаю ; RRRR - остальная часть типа, тут может быть подтип например ; ; offset 0x04 - other data for bus: number port, number bus, and etc. ; dword = 0xPPBBRRRR ; PP - port device ; BB - bus number ; RRRR - other data bus ; ; offset 0x08 ; dword = 0xDDDDVVVV ; DDDD - device id ; VVVV - vendor id ; ; offset 0x0C ; other data ; Type ; dword = 0xTTTTTTNN ; TTTTTT - type device ; 0xFF - unknown device type ; NN - motes for this type ; 0xFF - unknown device ;; ;; Kernel functions ;; ; for user api rcx/ecx = ptr to DEVICE rdx/edx = IOCTL_DEVICE call_device: cmp ecx, OS_BASE jae .err_struct cmp dword[ecx + DEVICE.magic],'_VED' jnz .err_struct cmp dword[ecx + DEVICE.size], sizeof.DEVICE jnz .err_struct cmp edx,OS_BASE jae .err_iocl test edx, edx jz .err_iocl cmp dword[ecx + DEVICE.func], 0 jz .err_func mov eax, ecx mov ecx, dword[ecx + DEVICE.data] ; for 64 kernel qword and rcx ; fastcall int iocl_func(void data, IOCTL_DEV* ioctl) call dword[eax + DEVICE.func] ret .err_struct: xor eax, eax dec eax ret .err_func: mov eax, -2 ret .err_iocl: mov eax, -3 ret ; for kernel api rcx/ecx = ptr to DEVICE rdx/edx = IOCTL_DEVICE call_device_k: cmp dword[ecx + DEVICE.magic],'_VED' jnz .err_struct cmp dword[ecx + DEVICE.size], sizeof.DEVICE jnz .err_struct cmp dword[ecx + DEVICE.func_k], 0 jz .err_func mov eax, ecx mov ecx, dword[ecx + DEVICE.data] ; for 64 kernel qword and rcx ; fastcall int iocl_func(void data, IOCTL_DEV* ioctl) call dword[eax + DEVICE.func_k] ret .err_struct: xor eax, eax dec eax ret .err_func: mov eax, -2 ret ;save pointers devices: .first: dd 0 dd 0 .last: dd 0 dd 0 ; for user and kernel api rcx/ecx = type device find_device: mov eax, [devices.first] test eax, eax jz .not_devices @@: cmp dword[eax + DEVICE.type], ecx jz .found cmp eax, dword[devices.last] mov eax, dword[eax + DEVICE.next] jnz @b xor eax, eax .not_devices: .found: ret ;use for kernel api ;fastcall void* AddDevice(void* subtype, void* data, void* array_func) ;data: *edx ; rd 2 ;например указатель на структуру или какой-то индекс в массиве структур ;array_func: *[esp + sizeof_pointer] ; type rd 2 ;тип устройства ; func rd 2;функция для вызова из юзермода ; func_k rd 2; функция для вызова из ядра ; exit rd 2 ; функция вызываемая при удалении устройства ;subtype: *ecx ; rd 4 ; данные устройства/уникальный идентификатор устройства/данные о шине по которой оно подкл. AddDevice: push ecx push edx mov eax, sizeof.DEVICE call malloc test eax, eax pop edx pop ecx jz .fail_mem mov edi, eax mov eax, [esp + 4] mov ebx, [devices.last] test ebx, ebx jnz @f mov [devices.first], edi mov [devices.last], edi jmp .set_data @@: mov [ebx + DEVICE.next], edi mov [edi + DEVICE.prev], ebx mov [devices.last], edi .set_data: mov [edi + DEVICE.magic], dword '_VED' mov [edi + DEVICE.size], sizeof.DEVICE push edi push ecx mov esi, eax mov ecx, 4 lea edi,[edi + DEVICE.type] rep movsd push esi mov esi,[esp + 4] mov ecx, 4 rep movsd add edi, 4*2 pop esi mov ecx, 4 rep movsd mov ecx, 2 mov esi, edx rep movsd add esp, 4 pop eax ret .fail_mem: or eax, -1 ret ;use for kernel api ;stdcall void DelDevice(void* ptr_struct) DelDevice: mov eax, [esp + 4] cmp dword[eax + DEVICE.magic],'_VED' jnz .err_struct cmp dword[eax + DEVICE.size], sizeof.DEVICE jnz .err_struct mov ecx, [eax + DEVICE.data] call [eax + DEVICE.exit] test eax, eax ; 0 - good -1 - error jz .no_exit ; delete item mov ecx, [eax + DEVICE.next] mov edx, [eax + DEVICE.prev] push ebx mov ebx,[devices.last] cmp ebx,[devices.first] jnz @f xor ebx, ebx mov [devices.first], ebx mov [devices.last], ebx jmp .free_struct @@: cmp eax, [devices.first] jnz @f mov [devices.first], ecx jmp .free_struct @@: cmp eax, [devices.last] jnz @f mov [devices.last], edx jmp .free_struct @@: mov [ecx + DEVICE.prev], edx mov [edx + DEVICE.next], ecx .free_struct: pop ebx call free ; eax = ptr to mem ret .no_exit: mov eax, -2 ret .err_struct: or eax, -1 ret ; find device from type ;eax = 81 ;ebx = 0 ;ecx = type ;out: rax/eax = pointer to device or null ; ;get list devices ;eax = 81 ;ebx = 1 ;out: rax/eax - first item, null for error ; rcx/ecx - last item ; ; get item list devices ;eax = 81 ;ebx = 2 ;rcx/ecx = pointer to device struct ;rdx/edx = pointer to buffer ;out: eax - error code: 0 - good; -1 - item not found -2 - Bad buffer ;buffer: ; .next: dd 0 ; dd 0 ; .prev: dd 0 ; dd 0 ; .type: dd 0 ; dd 0 ; .func: dd 0 ; может быть ноль, если драйвер не экспортирует функции для юзермода ; dd 0 ; .subtype: dd 0 ; dd 0 ; dd 0 ; dd 0 ;endbyff: ; call functiion device ;eax = 81 ;ebx = 3 ;ecx = pointer to device struct ;edx = pointer to IOCTL struct ;out: eax = Error code: 0-good -1-device dot found struct DEV_IOCL function dd 0 ; number subfunction size_input dd 0 size_output dd 0 ptr_input dd 0 dd 0 ptr_output dd 0 dd 0 ends ; subfunctions: ; 0-7 - mandatory ; 0 - get count subfunctions ; 1 - ger version device ; 2 - get driver ; 3 - get status device ; 4 - get name device ; 5 - get vendor ; 6 - lock device ;; for kernel and user api ; 7 - unlock device ;; for kernel and user api ;; ;; User API ;; sysfn81: test ebx, ebx jnz @f call find_device mov [esp + 32], eax ret @@: dec ebx ; =1 jnz @f mov eax, [devices.first] mov ecx, [devices.last] mov [esp + 32], eax mov [esp + 28], ebx ret @@: dec ebx ; =2 jnz @f cmp ecx, OS_BASE jae .err_struct cmp dword[ecx + DEVICE.magic],'_VED' jnz .err_struct cmp dword[ecx + DEVICE.size], sizeof.DEVICE jnz .err_struct stdcall is_region_userspace, ebx, sizeof.DEVICE jnz .bad_buffer mov esi, ecx mov edi, edx mov ecx, 12 ; 12 dword for buffer rep movsd and dword[esp + 32], 0 ret .bad_buffer: mov dword[esp + 32], -2 ret .err_struct: or dword[esp + 32], -1 ret @@: dec ebx ; =3 jnz @f call call_device mov [esp + 32], eax ret @@: or dword[esp + 32], -1 ret