Sterowniki
– pierwsze podejście
Sterownik urządzenia jest plikiem
wykonawczym systemu operacyjnego,
który zarządza komunikacją pomiędzy
fizycznym urządzeniem i programem
użytkownika
Pierścieniowy model systemu
operacyjnego
Podstawowa klasyfikacja ze
względu na funkcjonalność
Sterownik monolityczny
Sterownik filtrujący (filter driver)
Sterownik miniport
Sterownik monolityczny
zawierają w sobie wszystkie
funkcje potrzebne do
prawidłowego działania
urządzenia.
Dostęp do sterownika
monolitycznego ma jedna lub
kilka aplikacji.
bezpośrednio steruje
urządzeniem odwołując się do
niego poprzez funkcje IOCTL.
Filter drivers
są częścią stosu pomiędzy
urządzeniem a aplikacją
przejmuje wszystkie dane
transferowane do/z dysku.
znajduje się ponad
sterownikiem urządzenia i
zajmuje się tylko szyfrowaniem/
deszyfrowaniem danych
Miniport
Rozszerzenia do
sterowników
podstawowych
sterowniki do urządzeń HID
Sterownik NDIS jest
odpowiedzialny za wszystkie
protokoły transmisji a
sterownik Miniport jest tylko
dodatkiem dodającym nowe
funkcje.
Krótkie przypomnienie
Krótkie przypomnienie
Co to jest ten driver ?
Główny punkt wejściowy DriverEntry –
wywoływany tylko raz w trakcie
ładowania drivera do systemu
DRIVER_OBJECT (struktura inicjowana
przez DriverEntry)
Z punktu widzenia systemu operacyjnego
DRIVER_OBJECT jest widziany jako wskaźnik
do
wywoływania
dodatkowych
funkcji
odwołujących
się
do
urządzenia.
DRIVER_OBJECT
jest
tworzony
przez
sterownik i reprezentuje fizyczne lub wirtualne
urządzenie, które sterownik obsługuje.
Co to jest ten driver cz.2
DRIVER_OBJECT
jest
blokiem
pamięci
umieszczanym i częściowo inicjalizowanym przez
system operacyjny. Ten obiekt opisuje gdzie kod
sterownika jest ładowany do pamięci, nazwę
sterownika, oraz zawiera wskaźniki do adresów
funkcji, które sterownik oferuje. Jeden ze
wskaźników do adresów funkcji musi być
umieszczony w tablicy wskaźników nazwanej
„Function Dispatch Table”.
Function Dispatch Table
zawiera wejścia do każdej Major Function
Code oferowanej przez system operacyjny.
Obecnie istnieje 28 funkcji, które sterownik
może
zawierać,
jednak
w
większości
przypadków wystarcza obsługa 8 funkcji:
Major fuction Code
IRP_MJ_CREATE,
IRP_MJ_CLOSE,
IRP_MJ_READ,
IRP_MJ_WRITE,
IRP_MJ_PNP,
IRP_MJ_POWER,
IRP_MJ_DEVICE_CONTROL,
IRP_MJ_SYSTEM_CONTROL.
Windows Driver Model
Ściśle powiązane z NT (te same IRP
– I/O Request Packet)
W przeciwieństwie do NT obsługuje
PnP IRP oraz Power IRP
odpowiedzialność za sprzęt jest zrzucana
na sterownik szyny systemowej WDM
Tryb Kernel Mode
Nowy rodzaj sterownika typu class
Class Driver
Odpowiedzialne za podstawoe
funkcjie wspólne dla danej klasy
urządzeń (usb, firewire,HID) –
transmisja danych , odpowiednie
protokoły
Np. dla usb do komunikacji możemy
używać gotowych struktur danych
dostarczanych przez Classdriver -
URBs
DriverEntry
extern "C"
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Dri
verObject, IN PUNICODE_STRING RegistryPath
) { }
Tworzy jeden DeviceObject dla
każdego urządzenia
(IoCreateDevice)
Inicjalizacja drivera WDM, podczas
pierwszego ładowania
Prosty przykład
DriverEntry
extern "C"
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver
Object, IN PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = DriverUnload;
DriverObject->DriverExtension->
AddDevice = AddDevice;
DriverObject->
MajorFunction[IRP_MJ_PNP] = DispatchPnp;
DriverObject->
MajorFunction[IRP_MJ_POWER] = DispatchPower;
DriverObject->
MajorFunction[IRP_MJ_SYSTEM_CONTROL]=Dispat
chWmi;
servkey.Buffer =
(PWSTR) ExAllocatePool(PagedPool,
RegistryPath->Length + sizeof(WCHAR) );
if (!servkey.Buffer)
return STATUS_INSUFFICIE
NT_RESOURCES;
servkey.MaximumLength = RegistryPath
->Length + sizeof(WCHAR);
RtlCopyUnicodeString(&servkey, RegistryPath);
servkey.Buffer[RegistryPath
->Length/sizeof(WCHAR)] = 0;
return STATUS_SUCCESS; }
DriverObject
DriverObject - 1
HardwareDatabase
(PUNICODE_STRING)
to nazwa jak
\Registry\Machine\Hardware\Description\System
;w WDM nie istotna na programisty
FastIoDispatch
(PFAST_IO_DISPATCH)
wskazuje na
tablice wskaźników funkcji które eksportują
systemy plików i sterowniki sieciowe
DriverObject - 2
DriverStartIo (PDRIVER_STARTIO)
wskaźnik na
funkcje zajmujace się przetwarzanie żądań I/O uszeregowanych
przez I/O Manager
DriverUnload (PDRIVER_UNLOAD)
wskaźnik do
funkcji czyszczącej (WDM w zasadzie nie potrzebuje)
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{ RtlFreeUnicodeString(&servkey); }
MajorFunction (array of PDRIVER_DISPATCH)
tablica wskaźników do funkcji obsługujących I/O Requests
DEVICE OBJECT
DeviceObject - 1
NextDevice (PDEVICE_OBJECT)
Wskazuje na kolejne DeviceObject nalezące do
tego samego drivera
CurrentIrp (PIRP)
wskaznik na ostatni IRP
ze StartIo
Flags (ULONG)
DO_BUFFERED_IO ;
DO_EXCLUSIVE ; DO_DIRECT_IO ;
DO_DEVICE_INITIALIZING;
DO_POWER_PAGABLE ; DO_POWER_INRUSH
DeviceObject - 2
Characteristics (ULONG)
FILE_REMOVABLE_MEDIA;
FILE_READ_ONLY_DEVICE;
FILE_FLOPPY_DISKETTE;
FILE_WRITE_ONCE_MEDIA;
FILE_REMOTE_DEVICE;
FILE_DEVICE_IS_MOUNTED;
FILE_VIRTUAL_VOLUME;
FILE_AUTOGENERATED_DEVICE_NAME; I/O
FILE_DEVICE_SECURE_OPENA;
DeviceObject - 3
DeviceExtension (PVOID)
wskaźnik na
strukturę danych; zawiera informacje dotyczące każdego
wątku (urządzenia) obsługiwanego przez nasz driver; I/O
Manager alokuje dla tej struktury miejsce w pamięci, ale
definiowana jest całkowicie przez programistę
PDEVICE_EXTENSION pdx =
(PDEVICE_EXTENSION) fdo-> DeviceExtension;
DeviceType (DEVICE_TYPE) okresla jeden
z predefiniowany w wdm.h typów
urządzeń
AddDevice
NTSTATUS AddDevice
(PDRIVER_OBJECT DriverObject,
PDEVICE_OBJECT pdo)
{
return STATUS_SOMETHING;
// e.g., STATUS_SUCCESS
}
Co robi AddDevice?
Podstawowym zadaniem stworzenie
DriverObject i dowiązać go do stosu
zakorzenionego w PDO (Physical
Device Object)
Podstawowe kroki:
Wywołanie IoCreateDevice (device object
+ device extensions)
Rejestrowanie jednego lub więcej
interfejsów urządzenia bądź alternatywnie
nadanie nazwy temu urządzeniu
Inicjalizacja DeviceExtensions oraz Flags
Wywoładnie IoAttachDeviceToDeviceStack
Najprostszy
przykład
AddDevice
NTSTATUS AddDevice(PDRIVER_OBJECT Drive
rObject, PDEVICE_OBJECT pdo)
{
PDEVICE_OBJECT fdo;
NTSTATUS status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION), NULL,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN, FALSE, &fdo);
PDEVICE_EXTENSION pdx =
(PDEVICE_EXTENSION) fdo-
>DeviceExtension;
IoRegisterDeviceInterface (
pdo, &GUID_DEVINTERFACE_SIMPLE,
NULL, &pdx->ifname);
pdx->DeviceObject = fdo;
pdx->Pdo = pdo;
IoInitializeRemoveLock(&pdx->
RemoveLock, 0, 0, 0);
pdx->devstate = STOPPED;
pdx->devpower = PowerDeviceD0;
pdx->syspower = PowerSystemWorking;
IoInitializeDpcRequest(fdo, DpcForIsr);
if (MYDEVICE_ALIGNMENT - 1 > fdo->
AlignmentRequirement)
fdo->AlignmentRequirement=
MYDEVICE_ALIGNMENT- 1;
KeInitializeSpinLock(&pdx->SomeSpinLock);
KeInitializeEvent (&pdx->SomeEvent,
NotificationEvent, FALSE);
InitializeListHead(&pdx->SomeListAnchor);
fdo->
Flags
│= DO_BUFFERED_IO │ DO_POWER_PAGA
BLE;
fdo-> Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS; }
Dziękuje za uwagę
Dziękuje za uwagę
Dziękuje za uwagę
Dziękuje za uwagę