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
Статью не читаем, исходники не смотрим.
В папке kernel/trunk/drivers специально лежит sceletone.asm
Re: Написание драйвера.
Posted: Wed Jun 15, 2011 8:37 am
by popovpa
Статью я читаю раза 2 в день
Видимо не внимательно, но если не:
он даже не пишет:
То-есть не загружает?
Это в первом варианте, с макросами, а как быть во втором?
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, потому что само по себе ядро этого делать не будет. Во-вторых, ошибка в строке
Я поясню, откуда вообще берутся эти смещения. В часто используемой модели вызова 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