My goal is to demystify and make the process of install of filter drivers simpler. I spent time in this blog describing install issues, driver signing and some miscellaneous topics like PCI express capabilities. I will go into more depths of bus and class filter drivers in my next blog. In this blog I tackle the issues of deploying, debugging, signing filter drivers and small tidbits on PCI express capability structure defined in the PCI spec. There are lots of general guidelines in the Windows Driver Kit(WDK) on how to write filter drivers.
The figure below shows types of filter drivers and where a filter driver can be in the device stack.
The toaster filter driver in the WDK is a good starting point: http://msdn.microsoft.com/en-us/library/ff558716(v=VS.85).aspx The toaster sample set is huge and shows how to write different types of filter drivers – upper/lower class, bus and device filter. The filter deriver I recently wrote was a PCI bus filter driver and a USB class filter. Among other things the challenge was debugging and installing it.
Class filter – If you instantiate a CLASS filter, you do so for all devices in the CLASS. Thus, any new devices that are added in the filtered device class wind-up having the filter instantiated. More details here: http://msdn.microsoft.com/en-us/library/ff537905(v=vs.85).aspx
Bus filter drivers typically add value to a bus and are supplied by Microsoft or a system OEM. Bus filter drivers are optional. There can be any number of bus filter drivers for a bus. A bus filter driver could, for example, implement proprietary enhancements to standard bus hardware. For devices described by an ACPI BIOS, the power manager inserts a Microsoft-supplied ACPI filter (bus filter driver) above the bus driver for each such device. The ACPI filter carries out device power policy and powers on and off devices. The ACPI filter is transparent to other drivers and is not present on non-ACPI machines.
Debugging the pci bus filter – USB is not a great means for debugging it as the USB controllers which are PCI devices didn’t do too well when my filter driver hit a bug. That’s why resorted to 1394 and serial. I all my initial development and debugging on a desktop with serial ports and then started testing on a laptop. Inf file The install is challenging in how you need to write the inf file and then how do you install the filter driver. The places where this inf differs from a regular function drivers inf is the key to specify whether this is an upper or lower filter. Since this is a PCI bus filter it has the needs and Include directive as well since it is dependent on the PCI bus driver. Note the driver is a boot start since it is a PCI bus filter. It also uses the System class.
The highlighted part in bold below is the one unique to filter drivers.
[Version]
Signature=”$WINDOWS NT$”
Class=System
ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318}
Provider=%MSFT%
LayoutFile=layout.inf
DriverVer=09/21/2006,6.0.5736.1
[DestinationDirs]
DefaultDestDir = 12
[SourceDisksNames]
1 = %DiskId1%,,,””
[SourceDisksFiles]
PCIfilter.sys = 1,,
;*****************************************
; Install Section
;*****************************************
[Manufacturer]
%StdMfg%=Standard
[Standard]
%PCIfilter.DeviceDesc%=PCIfilter_Device, *PNP0A03
%PCIfilter.DeviceDesc%=PCIfilter_Device, *PNP0A08
[PCIfilter_Device.NT]
Include=machine.inf
Needs=PCI_DRV_ROOT
CopyFiles=Drivers_Dir
[PCIfilter_Device.NT.HW]
AddReg=PCIfilter_Device.NT.HW.AddReg
[Drivers_Dir]
PCIfilter.sys
[PCIfilter_Device.NT.HW.AddReg]
HKR,,”UpperFilters”,0x00010000,”PCIfilter”
;————– Service installation
; Function and filter driver for the bus
[PCIfilter_Device.NT.Services]
Include=machine.inf
Needs=PCI_DRV_ROOT.Services
AddService = PCIfilter,, PCIfilter_Service_Inst
; ————– busupper Driver install section
[PCIfilter_Service_Inst]
DisplayName = %PCIfilter.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 0 ; SERVICE_DEMAND_BOOT
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\PCIfilter.sys
LoadOrderGroup = PnP Filter
[Strings]
SPSVCINST_ASSOCSERVICE= 0x00000002
MSFT = “Microsoft”
StdMfg = “(Standard system devices)”
DiskId1 = ” PCI Bus
Installation Disk #1″
PCIfilter.SVCDESC = ” PCI Bus Upper Filter”
PCIfilter.DeviceDesc = ” PCI Bus filter”
Install:
devcon.exe install pcifilter.inf *PNP0A03
if the above fails
devcon.exe install pcifilter.inf *PNP0A08
NOTE: devcon.exe is a tool in the Wdk
Conmmand line way to right click and install an inf
rundll32 syssetup,SetupInfObjectInstallAction DefaultInstall 128 .\usbcfltr.inf
Reboot
You will need to reboot the system after install.
Installation on 64 bit system
You will need to enable test signing to install the filter or sign it.
bcedit /set testsigning ON
Debugging inf issues in install
To do this we need to turn on the verbosity
levels in the Setup logs to look at the Setupapidev.log .
The default value for log levels is 0x2000ff00
Turning the verbosity of logging
Setting SetupAPI Logging Levels
OSR’s link – http://osronline.com/ddkx/install/troubleshoot_7s6f.htm
Checking all the classfilters
For the USB class filter I wrote this command is what I used. More information in devcon help
devcon classfilter usb lower
Uninstall a class filter
- using devcon.exe
devcon -r classfilter usb lower !usbcfltr
- Registry
Renaming the key in the registry. For eg: If the name of the service is
usbcfltr, look for that in the registry and rename it.
Device stack after install of PCI filter driver
This is how the device stack looked for :
PCIbus
|
V
MyFilterdriver
|
V
ACPI
|
V
PCI root port
The attachedDevice field in the DEVICE_OBJECT structure points to the guy above him in the stack.
Getting PDO from an FDO
This is a common operation for writing filter drivers.
You can send an IRP_MN_QUERY_DEVICE_RELATIONS type TargetDeviceRelation down the stack to get a
referenced pointer to the PDO.
Signing Drivers during
Development and Test (Windows Vista and Later)
The following link describes the steps involved.
http://msdn.microsoft.com/en-us/library/ff552275.aspx
http://msdn.microsoft.com/en-us/library/ff552275(VS.85).aspx
The basic steps are outlined below with examples. Note the example just show one way of doing it and not the only way. You will need the WDK installed to use the tools for this.
- Create a certificate called testdriverfile
MakeCert -r -pe -ss PrivateCertStore -n “CN=testdriver” testdriverfile.cer
- Copy all the files to a folder which includes the .sys file, the inf file and any coinstallers like wdfcoinstaller01009.dll etc.
- Sign the driver sys file
SignTool sign /a /v /s PrivateCertStore /n testdriver /t http://timestamp.verisign.com/scripts/timestamp.dll .\cat\pcifilter.sys
- Generate the catalogue file.
Inf2Cat /v /driver:\signing\cat /os:7_X64
- Sign the cat fileSignTool sign /a /v /s PrivateCertStore /n testdriver /t http://timestamp.verisign.com/scripts/timestamp.dll .\cat\pcifilter.cat
- Install the certificate on the test machine
Certutil -addstore -f “Trusted Root Certification Authorities” testdriver.cer
Also run this command on the 64 bit system to allow test
bcedit /set testsigning ON
Miscellaneous tidbits about PCI express capabilities
- Format is capability _ptr followed by capability_id
- In the initial 255 bytes of the PCI space it uses 8 bytes for capability_ptr and 8 for capability_id
- PCI express extended capability region – After that it uses 16 bytes
for capability_id and then 1 byte for version and then 15 bytes for capability_ptr - Last cap has the capability_ptr field set to 0
- Following capability pointers
- Check status register – 0x6 bit 0x10 for cap ptr
- Register 0xe gives the type of PCI device type like Bridge, endpoint etc