Написание драйвера.
-
Я брал import.inc вот тут: (локальная копия svn) kolibrios.org\drivers
Странно. Может, подключается imports из какой-то другой папки? Хотя вряд ли.
Вопрос остается открытым.
Вопрос остается открытым.
То есть с кодом всё в принципе в порядке?
Статью не читаем, исходники не смотрим.
В папке kernel/trunk/drivers специально лежит sceletone.asm
Code: Select all
;public version
Статью я читаю раза 2 в день Видимо не внимательно, но если не:
он даже не пишет:
То-есть не загружает?
Это в первом варианте, с макросами, а как быть во втором?
Code: Select all
;public version
Code: Select all
in module .....
Это в первом варианте, с макросами, а как быть во втором?
version ведь не случайно public объявляется. Загрузчик драйвера проверяет версию драйверной модели.
Функция START тоже должна быть объявлена как public. Во втором случае этого не сделано.
Сделаем мир лучше!
В первом коде, действительно, нужно было public version, так заработало, тут моя невнимательность и торопливость, но во втором примере так нельзя сделать, пишет что символ переопределён...что тут можно сделать?
popovpa, подробнее, пожалуйста. У меня этот код с добавлением "public version" и "public START" не компилируется, но только потому, что imports.inc хочет объявления "DEBUG equ 1" - или "... equ 0" - до включения, после такого объявления компиляция успешна.
Сделаем мир лучше!
Простите, но было что-то странное, не компилировалось из тинипада, на доске отладки писало что данное имя уже используется, сейчас перезагрузился и всё откомпилировалось и запустилось без проблем...извините за беспокойство...видимо солнечная активность... разбираюсь дальше...
Здравствуйте!
Почему не выводится сообщение в service_proc:
И ещё 1 вопрос, структура ioctl служит для общения драйвера с операционной системой? И если да, то можно объяснить хоть в общих чертах что-же это всё таки такое.
Спасибо!
Почему не выводится сообщение в 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
Спасибо!
popovpa, во-первых, убедись, что управляющая программа вообще вызывает функцию 68.17, потому что само по себе ядро этого делать не будет. Во-вторых, ошибка в строке
Я поясню, откуда вообще берутся эти смещения. В часто используемой модели вызова stdcall - которая, в частности, применяется при вызове ядром service_proc - параметры кладутся в стек, начиная с последнего; поскольку стек растёт вниз, то перед вызовом stdcall-функции с параметрами arg1, arg2, arg3 стек выглядит так:
Вызов функции в x86 осуществляется путём сохранения в тот же стек адреса возврата - откуда его потом может достать команда ret - и передачи управления функции. Таким образом, esp уменьшается на 4 и перед первой инструкцией функции стек выглядит так:
Поскольку esp в пределах функции часто "плавает", то везде адресовать относительно esp неудобно, хотя и можно. Кроме того, адресация через esp длиннее на байт. Поэтому часто начальное значение esp копируется в ebp, который уже не "плавает", и смещения относительно ebp постоянны. В модели вызова stdcall функция не должна разрушать регистр ebp - между прочим, к регистрам ebx, esi, edi это тоже относится - поэтому его нужно сохранить в том же стеке, а при выходе не забыть восстановить. Первая инструкция push ebp сохраняет текущее значение ebp, после чего esp ещё немного "уплывает" и стек выглядит так:
В этот момент регистру ebp присваивается значение esp, и внутри функции дальше можно обращаться к аргументам так:
Структура IOCTL используется для передачи драйверу запросов из внешнего мира - обычно из приложения посредством функции 68.17. Сама структура содержит параметры этих запросов - код запроса и, опционально, указатели на входные и/или выходные данные и размеры этих данных. Драйвер обращается к внешнему миру посредством API ядра, объявленных в imports.inc.
Code: Select all
mov ebx,[ebp+4]
Code: Select all
arg3 <- esp+8
arg2 <- esp+4
arg1 <- esp - верхушка стека
Code: Select all
arg3 <- esp+12
arg2 <- esp+8
arg1 <- esp+4
адрес возврата <- esp
Code: Select all
arg3 <- esp+16
arg2 <- esp+12
arg1 <- esp+8
адрес возврата <- esp+4
сохранённое значение ebp <- esp
Code: Select all
arg3 <- ebp+16
arg2 <- ebp+12
arg1 <- ebp+8
адрес возврата <- ebp+4
сохранённое значение ebp <- ebp
Сделаем мир лучше!
Попробую ответитьИ ещё 1 вопрос, структура ioctl служит для общения драйвера с операционной системой? И если да, то можно объяснить хоть в общих чертах что-же это всё таки такое.
После команды загрузки драйвера (68.16) ядро выделяет память под драйвер загружает, и после успешной проверки передает ему управление на точку START. Далее идет твой код до точки REG_SERVICE, после передается управление этой подпрограмме в ядре которая регистрирует точку входа твоей подпрограммы с параметром service_proc ну и еще кое какой хлам.Если все пройдет нормально то подпрограмма вернет тебе HENDL твоего драйвера, и драйвер должен вернуть управление системе. После вызова функции 68.17 по ХЕНДЛУ ядро по таблице находит точку входа service_proc и передает управление ей. А структура ioctl это кусок памяти в твоем приложении, где ты сохраняешь ХКНДЛ, код функции ,длину и т.д. драйвер если сказать проще открывает ТОННЕЛЬ к ней.
Все сложное - просто!
Здравствуйте!
Я не оставил надежд написать драйвер, пишу драйвер для своей wi-fi (встроенной) карточки. Так как тема явно растянется, прошу модератором переименовать тему в что-то подобное: "Драйвер для bcm43xx"...
А теперь собственно вопросы:
Я нашёл своё устройство, спасибо sceletone.asm. Затем как я понял необходимо считать Base Address Registers, а уже зная его, считывать данные из устройства (это будут смещения относительно этого адреса?). Дальше у меня есть драйвер для моей карточки под Linux, но я так и не смог с ним разобраться, точнее если первое утверждение было верное, я не смог найти смещения которые надо считывать или записывать, может кто-то более опытный взглянет краем глаза и ткнёт носом что примерно и где искать? Буду очень благодарен. Или я всё не правильно понял? А если так может посоветуете что почитать, желательно на русском, чтобы я стал на пол миллиметра ближе к профи....
Спасибо!
Я не оставил надежд написать драйвер, пишу драйвер для своей wi-fi (встроенной) карточки. Так как тема явно растянется, прошу модератором переименовать тему в что-то подобное: "Драйвер для bcm43xx"...
А теперь собственно вопросы:
Я нашёл своё устройство, спасибо sceletone.asm. Затем как я понял необходимо считать Base Address Registers, а уже зная его, считывать данные из устройства (это будут смещения относительно этого адреса?). Дальше у меня есть драйвер для моей карточки под Linux, но я так и не смог с ним разобраться, точнее если первое утверждение было верное, я не смог найти смещения которые надо считывать или записывать, может кто-то более опытный взглянет краем глаза и ткнёт носом что примерно и где искать? Буду очень благодарен. Или я всё не правильно понял? А если так может посоветуете что почитать, желательно на русском, чтобы я стал на пол миллиметра ближе к профи....
Спасибо!
Способ обращения зависит от того, располагается BAR в I/O пространстве или в памяти. Разные BARы одного устройства могут жить в разных пространствах. Младший бит каждого BARа - read-only, 1 для BARов в I/O, 0 для BARов в памяти. Для конкретного устройства один и тот же регистр всегда находится в одном и том же пространстве, хотя конкретный адрес можно изменять. Каждый BAR задаёт базовый адрес некоторого диапазона адресов; смещения регистров внутри диапазона фиксированы. Детали
Для BARов из I/O пространства базовый адрес есть значение BARа с обнулёнными двумя младшими битами, обращение осуществляется командами in/out:
Для 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
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
Сделаем мир лучше!
Who is online
Users browsing this forum: No registered users and 3 guests