|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Июн 10, 2004 02:05:36 Привет всем! Решил начать помаленьку приобщаться к драйверостроению. Прочитал, на досуге, вводные статьи из серии: 'Драйверы режима ядра', вышедшие из под пера Four-F. Было очень интересно. К сожалению, кое-что я не понял... В третей части, описан драйвер: giveio.sys. Этот драйвер демонстрирует работу с IOPM. Не понятно в нем следующее: 1. Я всегда думал, что каждый процесс в системе имеет свою IOPM. Если это так, то не понятно: каким образом функции Ke386QueryIoAccessMap и Ke386SetIoAccessMap, получают доступ к IOPM процесса управляющего драйвером? Ведь эти функции вызываются в процедуре: DriverEntry, а она выполняется в контексте системного процесса. По идее, здесь они должны работать с IOPM, какого ни будь системного процесса, а не программы управления драйвером. 2. Далее, мне непонятно: почему при получении IOPM с помощью функции Ke386QueryIoAccessMap, не производится копирование уже существующей IOPM, а по сути, создается новая IOPM, которая закрывает доступ ко всем портам ввода-вывода? А если у процесса уже были открыты какие-то порты ввода-вывода? 3. В конце процесса настройки IOPM, вызывается функция: Ke386IoSetAccessProcess, которая разрешает указанному процессу пользоваться его IOPM. Почему же, перед началом процесса настройки я не вижу функции, которая бы запретила указанному процессу пользоваться его IOPM? Или этот запрет стоит по умолчанию? Заранее благодарен за ваши ответы! |
|
|
Дата: Июн 10, 2004 14:25:37 · Поправил: Four-F [ Oleg_SK: Я всегда думал, что каждый процесс в системе имеет свою IOPM. ] Я тоже так думал. В статье "Часть 3: Простейшие драйверы" фраза "...процессор поддерживает гибкий механизм защиты, позволяющий операционной системе предоставлять доступ к любому подмножеству портов ввода-вывода для каждого отдельно взятого процесса." верна но... Дело вот в чем. Интел задумывал, что TSS будет привязан к каждой задаче (процессу). Т.е. сколько процессов, столько и TSS. Т.к. IOPM привязана к TSS, то получалось, что для каждого процесса можно настроить её независимо от других. Но Windows не использует задумку Интел и мы имеем всего один TSS на все процессы. И IOPM тоже одна! Количество TSS Поэтому (по крайней мере, на однопроцессорной машине) ситуация следующая: Ke386QueryIoAccessMap никакого query не делает, а фактически заполняет переданный ей массив значениями 0FFh. BOOLEAN
Ke386QueryIoAccessMap (
ULONG MapNumber,
PKIO_ACCESS_MAP IoAccessMap
)
memset(IoAccessMap, -1, IOPM_SIZE);
return TRUE;
}
Ke386SetIoAccessMap просто копирует переданную ей карту в TSS по смещению 88h от начала. И эта новая карта может быть использована всеми процессами! Для того чтобы процесс мог использовать карту надо просто поместить смещение 88h в его KPROCESS.IopmOffset, что и делает Ke386IoSetAccessProcess. Т.о. для Ke386QueryIoAccessMap и Ke386SetIoAccessMap контекст по-барабану, а Ke386IoSetAccessProcess явно использует указатель на объект. Простой экскримент: Запускаем DateTime.exe. После этого любой процесс может юзать 70h и 71h порты, если его KPROCESS.IopmOffset поставить в 88h. Берем DateTime.asm, переписываем его start таким образом: start proc
invoke MessageBox, 0, 0, 0, 0
invoke DateTime
invoke ExitProcess, 0
start endp
Запускаем. Пока висит MessageBox заходим в айс, набираем <proc DateTime> - плучаем указатель на его KPROCESS. Набираем <ew указатель+30> и влупляем туда 0088. Отпускаем MessageBox и вуаля... спокойно читаем порты. Смещение IopmOffset равно 30h для w2k, xp и 2003. Так что не боитесь :) ЗЫ: Гуглим по TSS и IOPM, берем доки по камням, изучаем \private\ntos\ke\i386\iopm.c, экскрементируем в айсе - делаем выводы. |
|
|
Дата: Июн 11, 2004 04:54:39 Four-F Я рад вашему ответу! Все поставленные вопросы, благодаря нему, сняты. К сожалению, вынужден констатировать, что этот механизм (я имею в виду механизм предоставления возможности приложениям пользовательского режима непосредственно работать с I/O-портами) не может ГАРАНТИРОВАННО выполнять свою задачу, т.к. если в системе одновременно будет выполняться несколько независимых приложений, которые используют этот механизм, то конфликты между ними неизбежны. Причиной этому является функция Ke386QueryIoAccessMap, которая почему-то игнорирует свой первый аргумент и не дает нам получить текущее состояние IOPM. Более того, использование этого способа может быть опасно по той причине, что видео драйвер, возможно, тоже использует этот (или подобный) механизм (во всяком случае, Дейл Робертс, в своей статье, говорит о такой возможности). Если это так, то возможен конфликт между нашим приложением и видеодрайвером. Я очень надеюсь что ошибаюсь. Если это так, то поправьте меня. |
|
|
Дата: Июн 11, 2004 14:04:50 [ Oleg_SK: функция Ke386QueryIoAccessMap, которая почему-то игнорирует свой первый аргумент и не дает нам получить текущее состояние IOPM ] Пардон, я немного не верно выразился и тот код сильно упрощен и показывает, что делает Ke386QueryIoAccessMap, если первый параметр = 0. На мой взгляд этот флаг абсолтно не логичен. Если функция Query, то какого хрена она еще и Set делает. Если первый параметр = 1, то всё ОК - получим текущую карту, но только она глобальна для всей системы, а не для процесса, как можно понять из моей статьи. Если там какой-то бит сброшен, то значит кто-то уже юзает эту фичу. Если сброшенные биты не трогать, то конфликта не должно быть. Т.е. надо просто четко понимать, что карта глобальна. Т.о. код giveio надо чуть подправить. Вместо invoke Ke386QueryIoAccessMap, 0, pIopm д.б. invoke Ke386QueryIoAccessMap, 1, pIopm Тогда все ОК. Век живи - век учись. Исходнички винды сильно помогают, однако :) Oleg_SK, давай "на ты". |
|
|
Дата: Июн 11, 2004 17:49:58 Four-F я, как и Oleg_SK, с удовольствием прочитал твой курс (драйверов я сам никогда не писАл, и с их авторами не знаком (х)сами-знаете-кто :)), но меня интересует момент отладки драйверов, который, не мой взгяд, не достаточно полно освещен в статье. всегда есть большая вероятность (для начинающих) получить ситуацию, когда тестируемый драйвер валит систему в bsod. переставлять систему каждый раз неприкольно, посему вопрос, как с этим борешься ты? вариантов (у меня) напрашивается два: 1. тестировать драйвер под типа vmware 2. закладывать некую логику при старте драйвера, типа if fileexists('1.txt') then goto exit; createfile('1.txt') ... // initialization @exit: как с этим борешься ты, что посоветуешь? |
|
|
Дата: Июн 11, 2004 19:00:58 Во-первых, я следую принципу "семь раз отмерь, один отрежь". Перед запуском драйвера тщательно перепроверяю код. Во-вторых, я стараюсь, по возможности, двигаться мелкими шагами: написАл чуть кода - пошел проверил в отладчике. В-третьих, расставляю побольше int 3 в потенциально опасных местах и в айсе очень внимательно топчу F8. В-четвёртых, обязательно перед запуском драйвера запускаю sync.exe. Вот такие простые правила. К BSOD'у я уже привык и не особо его боюсь. Такого, чтоб всё настолько глобально кирдыкнулось, что систему нужно переставлять никогда не было. Единственная неприятность - скандиск долго копается :) |
|
|
Дата: Июн 13, 2004 01:41:33 · Поправил: Oleg_SK Four-F Т.е. надо просто четко понимать, что карта глобальна. Да, это стало понятно еще при прочтении первого вашего ответа (хотя догадываться я об этом стал уже через 5 мин., после того как создал этот топик). Тут появился еще один вопрос. Он не связан напрямую с технологией драйверостроения, но раз он относится к вашим статьям по этой теме, я решил задать его здесь... Вопрос связан вот с чем: для демонстрации функционирования механизма предоставления возможности приложениям пользовательского режима непосредственно работать с I/O-портами, вы в управляющей программе, драйвера: giveio.sys, производите прямые операции с CMOS через I/O-порты. В книге М.Гука, 'Энциклопедия. Аппаратные средства IBM PC', которую я использую для изучения соответствующей темы, на стр.89, говорится: 'Доступ к ячейкам CMOS RTC осуществляется через порты ввода/вывода 070h(индекс ячейки) и 071h(данные). Поскольку эта память имеет быстродействие порядка единиц микросекунд, между командами записи адреса и чтения/записи данных необходима программная задержка.'. В то же время, в ваших исходниках, такая задержка не делается. Вопрос: почему код, не смотря на это, работает нормально? |
|
|
Дата: Июн 13, 2004 02:05:08 нормально работает? а ты запусти его на 486 :))) з.ы. когда что-либо читаешь, желательно еще _продумать_ то, о чем пишет автор |
|
|
Дата: Июн 24, 2004 18:33:42 Mad_C Sorry за долгое молчание. Небыло выхода в сеть. К сожалению, ваше сообщение IMHO - мало информативно! нормально работает? а ты запусти его на 486 :))) К сожалению, у меня нет доступа к такой машине. Но, даже если бы доступ был, врядли я стал бы устанавливать ось семейства NT (ведь в статьях Four-F приведены драйвера именно для этих осей) на четверку... Не знаю как NT4 (т.к. я с ней не сталкивался), а для Windows 2000 необходим как минимум Pentium 133Mhz... Но это так, к слову. Я к сожалению, так и не понял: почему на процах 486- задержка требуется, а на P5+ - нет? У себя я такой инфы не нашел. когда что-либо читаешь, желательно еще _продумать_ то, о чем пишет автор Что верно, то верно! Но к сожалению, времени на это не всегда хватает, так что я могу что-то упустить :( Please, ткните пальцем туда, где, по вашему мнению, я что-то упустил. |
|
|
Дата: Июн 27, 2004 17:02:40 IA-32 Intel Architecture Software Developer’s Manual Volume 1 : Basic Architecture 12.1. I/O PORT ADDRESSING . . . One benefit of using the I/O address space is that writes to I/O ports are guaranteed to be completed before the next instruction in the instruction stream is executed. Thus, I/O writes to control system hardware cause the hardware to be set to its new state before any other instructions are executed. See Section 12.6., “Ordering I/O”, for more information on serializing of I/O operations. Короче, пень сам с этим разбирается. В HAL вызовы IN/OUT постоянно перемежаются jmp $+2. CMOS_READ MACRO
OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
IODelay ; I/O DELAY
IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA
IODelay ; I/O DELAY
ENDM
;++
;
; IODELAY
;
; Macro Description:
;
; This macro simply does a jmp to next instruction to synchronize
; IO port access.
;
; Arguments:
;
; None
;
;--
IODELAY macro
jmp $+2
endm
Зачем это надо, я не совсем понимаю, ибо в том же интеловском мануале написано: "The processor synchronizes I/O instruction execution with external bus activity (see Table 12-1)." и табличка дана. И ещё одна фича. CMOS может находится в состоянии обновления. Нужно в цикле проверять флаг CMOS_STATUS_BUSY и если CMOS не занят апдейтом читать. CMOS_STATUS_BUSY EQU 80H ; Time update in progress
. . .
mov ecx, 100
align 4
krct00: mov al, 0Ah ; Specify register A
CMOS_READ ; (al) = CMOS register A
test al, CMOS_STATUS_BUSY ; Is time update in progress?
jz short krct10 ; if z, no, go read CMOS time
loop short krct00 ; otherwise, try again.
;
; CMOS is still busy. Try again ...
; |
|
|
Дата: Июн 27, 2004 18:36:43 · Поправил: Oleg_SK Four-F Зачем это надо, я не совсем понимаю... Вариант ответа № 1: Видимо это надо, если этот код будет работать на процах 386 и младше (причем, на некоторых моделях процов 386 этот способ задержки не сработает). Если же этот код будет работать на процах Pentium+, то этот способ задержки не прокатит, т.к. они имеют внутренний кэш, но проблем тут из-за этого не будет потому что (как ты и сказал) пень сам с этим разбирается. Непонятно только то, как этот код будет работать на процах 486 и некоторых моделях 386? Дело в том, что этот способ задержки на них не сработает по причине наличия у них внутреннего кэша, а с другой стороны (как говорит Mad_C), они не смогут сами разобраться с этим, так как это делают пни)... Вариант ответа № 2: А с какой оси этот HAL? Если с Win2000+, то похоже что это - рудименты... |
|
|
Дата: Июн 27, 2004 18:46:16 · Поправил: Four-F NT4. Тогда 386 ещё был актуален :) В ХР и 2003 та же история - jmp short $. А хрюшу на 386 пущать это даже не мозохизм ... :) |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.116 |