Page 2 of 3

Re: Написание драйвера.

Posted: Tue Jun 14, 2011 8:13 pm
by popovpa
Я брал import.inc вот тут: (локальная копия svn) kolibrios.org\drivers

Re: Написание драйвера.

Posted: Tue Jun 14, 2011 8:17 pm
by SoUrcerer
Странно. Может, подключается imports из какой-то другой папки? Хотя вряд ли.
Вопрос остается открытым.

Re: Написание драйвера.

Posted: Tue Jun 14, 2011 9:07 pm
by popovpa
То есть с кодом всё в принципе в порядке?

Re: Написание драйвера.

Posted: Wed Jun 15, 2011 8:02 am
by Serge
Статью не читаем, исходники не смотрим.

Code: Select all

;public version
В папке kernel/trunk/drivers специально лежит sceletone.asm

Re: Написание драйвера.

Posted: Wed Jun 15, 2011 8:37 am
by popovpa
Статью я читаю раза 2 в день :) Видимо не внимательно, но если не:

Code: Select all

;public version
он даже не пишет:

Code: Select all

in module .....
То-есть не загружает?

Это в первом варианте, с макросами, а как быть во втором?

Re: Написание драйвера.

Posted: Wed Jun 15, 2011 8:50 am
by Serge
version ведь не случайно public объявляется. Загрузчик драйвера проверяет версию драйверной модели.

Re: Написание драйвера.

Posted: Wed Jun 15, 2011 12:11 pm
by CleverMouse
Функция START тоже должна быть объявлена как public. Во втором случае этого не сделано.

Re: Написание драйвера.

Posted: Wed Jun 15, 2011 1:38 pm
by popovpa
В первом коде, действительно, нужно было public version, так заработало, тут моя невнимательность и торопливость, но во втором примере так нельзя сделать, пишет что символ переопределён...что тут можно сделать?

Re: Написание драйвера.

Posted: Wed Jun 15, 2011 3:44 pm
by CleverMouse
popovpa, подробнее, пожалуйста. У меня этот код с добавлением "public version" и "public START" не компилируется, но только потому, что imports.inc хочет объявления "DEBUG equ 1" - или "... equ 0" - до включения, после такого объявления компиляция успешна.

Re: Написание драйвера.

Posted: Wed Jun 15, 2011 3:59 pm
by popovpa
Простите, но было что-то странное, не компилировалось из тинипада, на доске отладки писало что данное имя уже используется, сейчас перезагрузился и всё откомпилировалось и запустилось без проблем...извините за беспокойство...видимо солнечная активность...:) разбираюсь дальше...

Re: Написание драйвера.

Posted: Wed Jun 22, 2011 8:33 pm
by popovpa
Здравствуйте!

Почему не выводится сообщение в service_proc:

Code: Select all

mov	esi, msgProc
call	SysMsgBoardStr

Code: Select all

format MS COFF

include 'proc32.inc'
include 'imports.inc'

OS_BASE 	equ 0;
new_app_base	equ 0x60400000
PROC_BASE	equ OS_BASE+0x0080000

struc IOCTL
{  .handle	dd ?
   .io_code	dd ?
   .input	dd ?
   .inp_size	dd ?
   .output	dd ?
   .out_size	dd ?
}

virtual at 0
  IOCTL IOCTL
end virtual

public START
public service_proc
public version

section '.flat' code readable align 16

START:
	push	ebp
	mov	ebp,esp
	mov	eax,[ebp+8]

	cmp	eax,1
	jnz	.exit

	mov	esi, msgStart
	call	SysMsgBoardStr

	push	service_proc
	push	my_service
	call	RegService

	pop	ebp
	ret	4

.exit:
	mov	esi, msgBad
	call	SysMsgBoardStr

	pop	ebp
	xor	eax,eax
	ret	4

handle	   equ	IOCTL.handle
io_code    equ	IOCTL.io_code
input	   equ	IOCTL.input
inp_size   equ	IOCTL.inp_size
output	   equ	IOCTL.output
out_size   equ	IOCTL.out_size

service_proc:

	push	ebp
	mov	ebp,esp

	   mov ebx, [ebp+4]
	   mov eax, [ebx+io_code]
	   cmp eax, 0
	   jne @F

	   mov eax, [ebx+output]
	   cmp [ebx+out_size], 4
	   jne .fail
	   mov [eax], dword 0

	mov	esi, msgProc
	call	SysMsgBoardStr

	   xor eax, eax
	   ret
@@:
.fail:

	mov	esi, msgProc
	call	SysMsgBoardStr

	   or eax, -1
	   ret


version 	dd	0x50005
my_service	db	'bcm4312',0

section '.data' data readable writable align 16


msgStart db 'Start...',0
msgProc db 'Proc...',0
msgBad db 'Bad...',0
И ещё 1 вопрос, структура ioctl служит для общения драйвера с операционной системой? И если да, то можно объяснить хоть в общих чертах что-же это всё таки такое.

Спасибо!

Re: Написание драйвера.

Posted: Wed Jun 22, 2011 9:14 pm
by CleverMouse
popovpa, во-первых, убедись, что управляющая программа вообще вызывает функцию 68.17, потому что само по себе ядро этого делать не будет. Во-вторых, ошибка в строке

Code: Select all

mov ebx,[ebp+4]
Я поясню, откуда вообще берутся эти смещения. В часто используемой модели вызова stdcall - которая, в частности, применяется при вызове ядром service_proc - параметры кладутся в стек, начиная с последнего; поскольку стек растёт вниз, то перед вызовом stdcall-функции с параметрами arg1, arg2, arg3 стек выглядит так:

Code: Select all

arg3 <- esp+8
arg2 <- esp+4
arg1 <- esp - верхушка стека
Вызов функции в x86 осуществляется путём сохранения в тот же стек адреса возврата - откуда его потом может достать команда ret - и передачи управления функции. Таким образом, esp уменьшается на 4 и перед первой инструкцией функции стек выглядит так:

Code: Select all

arg3 <- esp+12
arg2 <- esp+8
arg1 <- esp+4
адрес возврата <- esp
Поскольку esp в пределах функции часто "плавает", то везде адресовать относительно esp неудобно, хотя и можно. Кроме того, адресация через esp длиннее на байт. Поэтому часто начальное значение esp копируется в ebp, который уже не "плавает", и смещения относительно ebp постоянны. В модели вызова stdcall функция не должна разрушать регистр ebp - между прочим, к регистрам ebx, esi, edi это тоже относится - поэтому его нужно сохранить в том же стеке, а при выходе не забыть восстановить. Первая инструкция push ebp сохраняет текущее значение ebp, после чего esp ещё немного "уплывает" и стек выглядит так:

Code: Select all

arg3 <- esp+16
arg2 <- esp+12
arg1 <- esp+8
адрес возврата <- esp+4
сохранённое значение ebp <- esp
В этот момент регистру ebp присваивается значение esp, и внутри функции дальше можно обращаться к аргументам так:

Code: Select all

arg3 <- ebp+16
arg2 <- ebp+12
arg1 <- ebp+8
адрес возврата <- ebp+4
сохранённое значение ebp <- ebp
Структура IOCTL используется для передачи драйверу запросов из внешнего мира - обычно из приложения посредством функции 68.17. Сама структура содержит параметры этих запросов - код запроса и, опционально, указатели на входные и/или выходные данные и размеры этих данных. Драйвер обращается к внешнему миру посредством API ядра, объявленных в imports.inc.

Re: Написание драйвера.

Posted: Thu Jun 23, 2011 12:06 pm
by G@K
И ещё 1 вопрос, структура ioctl служит для общения драйвера с операционной системой? И если да, то можно объяснить хоть в общих чертах что-же это всё таки такое.
Попробую ответить

После команды загрузки драйвера (68.16) ядро выделяет память под драйвер загружает, и после успешной проверки передает ему управление на точку START. Далее идет твой код до точки REG_SERVICE, после передается управление этой подпрограмме в ядре которая регистрирует точку входа твоей подпрограммы с параметром service_proc ну и еще кое какой хлам.Если все пройдет нормально то подпрограмма вернет тебе HENDL твоего драйвера, и драйвер должен вернуть управление системе. После вызова функции 68.17 по ХЕНДЛУ ядро по таблице находит точку входа service_proc и передает управление ей. А структура ioctl это кусок памяти в твоем приложении, где ты сохраняешь ХКНДЛ, код функции ,длину и т.д. драйвер если сказать проще открывает ТОННЕЛЬ к ней.

Re: Написание драйвера.

Posted: Wed Aug 24, 2011 4:44 pm
by popovpa
Здравствуйте!

Я не оставил надежд написать драйвер, пишу драйвер для своей wi-fi (встроенной) карточки. Так как тема явно растянется, прошу модератором переименовать тему в что-то подобное: "Драйвер для bcm43xx"...

А теперь собственно вопросы:

Я нашёл своё устройство, спасибо sceletone.asm. Затем как я понял необходимо считать Base Address Registers, а уже зная его, считывать данные из устройства (это будут смещения относительно этого адреса?). Дальше у меня есть драйвер для моей карточки под Linux, но я так и не смог с ним разобраться, точнее если первое утверждение было верное, я не смог найти смещения которые надо считывать или записывать, может кто-то более опытный взглянет краем глаза и ткнёт носом что примерно и где искать? Буду очень благодарен. Или я всё не правильно понял? А если так может посоветуете что почитать, желательно на русском, чтобы я стал на пол миллиметра ближе к профи....

Спасибо!

Re: Написание драйвера.

Posted: Wed Aug 24, 2011 8:10 pm
by CleverMouse
Способ обращения зависит от того, располагается BAR в I/O пространстве или в памяти. Разные BARы одного устройства могут жить в разных пространствах. Младший бит каждого BARа - read-only, 1 для BARов в I/O, 0 для BARов в памяти. Для конкретного устройства один и тот же регистр всегда находится в одном и том же пространстве, хотя конкретный адрес можно изменять. Каждый BAR задаёт базовый адрес некоторого диапазона адресов; смещения регистров внутри диапазона фиксированы. Детали
Для BARов из I/O пространства базовый адрес есть значение BARа с обнулёнными двумя младшими битами, обращение осуществляется командами in/out:

Code: Select all

; если eax = значение BAR
and al,not 3
lea edx,[eax+DeviceRegister]
in {al|ax|eax},dx ; al/ax/eax = register value
out dx,{al|ax|eax} ; set register value to al|ax|eax
Для BARов в памяти базовый физический адрес есть значение BARа с обнулёнными четырьмя младшими битами. Прежде чем использовать такой диапазон, о нём нужно известить ОС, после чего с ним можно работать как с любой памятью:

Code: Select all

; если eax = значение BAR
and al,not 0Fh
stdcall MapIoMem,eax,<size>,1Bh ; PG_SW+PG_NOCACHE, kernel-writable non-cacheable memory range
test eax,eax
jz die
mov ecx,[eax+DeviceRegister] ; ecx = register value
or dword [eax+DeviceRegister],10000h ; set bit in the register