Hardware initialisation and Device Driver Loading using udev.
- This is probably out of date now... I wrote it to get some things clear in my head....
- The Summary below gives an overview of the process that takes place when a device is configured using udevd. For each numbered section in the summary there is a link to longer sections ( below the summary ) which go into greater detail.
Summary.
- [1] H/W is plugged in.
- [2] kernel creates a "uevent" for the udev daemon (/sbin/udevd)
- [3] udevd calls /sbin/hwup to load driver module and initialise device
- [4a] /sbin/hwup reads device specific config file from /sysconfig/hardware/<config>
- [4b] If no such config file exists uses sysfs (/sys/... ) to find modalias
- [5] Module configuration info is passed back to the udevd.
- [6] udevd calls /sbin/modprobe to load driver module. if hwup used step [4b] modprobe will use modalias to find correct module from /etc/modules/<kernel_version>/modules.aliases
- [7] udevd creates device files according to contents of /etc/udev/rules.d/
udev informs applications of the new device through the Hardware Abstraction Layer ( HAL )
Long Version.
- /sbin/udevd which is started from /etc/init.d/boot.d/S03boot.udev.
- At start time the udevd daemon created static devices using the following command :-
- /sbin/udev.create_static_devices.sh /etc/udev/static_devices.txt
- /sbin/udevd also checks to see if the kernel was compiled with the KOBJECT_UEVENT system variable set and if so enables uevent messaging. if not it uses :/sbin/udevsend and configures this by:-
- echo "/sbin/udevsend" > /proc/sys/kernel/hotplug
- and udevd is NOT started.
- Kernel uevents and udevd activity can be monitored with /usr/sbin/udevmonitor ( must be root ) , included in the output is the device path of the newly :added / removed hardware.
- [3] udevd calls /sbin/hwup to load driver module and initialise device.
- hwup is called with the hardware descripton as an argument e.g
hwup bus-pci-0000:01:00.0
- ( Use /sbin/lspci to show pci bus paths for different devices. hwdown <h/w_desc> can be used to stop a device ( leaving the module still inserted .) and :similiarly hwstatus <h/w_desc> reports on modules used for a device.)
- [4a] /sbin/hwup uses this hardware descriptor argument to read a specific config file from /sysconfig/hardware/
pjohnson@osslin7:/dev> ls /etc/sysconfig/hardware
config hwcfg-bus-pci-0000:00:1f.5 hwcfg-bus-pci-0000:01:00.0 hwcfg-static-printer
- The filenames follow a pattern by which the hwup command can identify a config file that relates to a specific piece of hardware. The contents of this :config file are then used to find a device driver module.
pjohnson@osslin7:/etc/sysconfig/hardware> cat hwcfg-bus-pci-0000:01:00.0
MODULE='tg3'
MODULE_OPTIONS=''
STARTMODE='auto'
- This module information is then passed back to the udev daemon.
- [4b] If there is no such config file as described in section [4a] hwup uses the kernel provided "sysfs" (/sys/.... ) to retrieve information describing :the hardware so that the correct module can be loaded.
ls /sys/bus/pci/devices/
. 0000:00:00.0 0000:00:03.0 0000:00:1d.0 0000:00: 1d.2 0000:00:1d.7 0000:00:1f.0 0000:00:1f.2 0000:01:00.0
.. 0000:00:02.0 0000:00:04.0 0000:00:1d.1 0000:00:1d.3 0000:00:1e.0 0000:00:1f.1 0000:00: 1f.5 0000:40:00.0
- ( Again, you can use /sbin/lspci to see what devices are connected to your pci bus. )
osslin7:/sys/bus/ide/devices # ls
0.0 1.0
- If we look at the contents of one device's directory ( in this case the network card )
osslin7:/sys/bus/pci/devices/0000:01:00.0 # ls
bus class config device driver irq local_cpus modalias power resource resource0 subsystem_device subsystem_vendor vendor
- Certain hardware identifiers have been taken from the card and placed into files ( within the sysfs filesystem ) such as the hex vendor and device :identifiers. ( all PCI vendor IDs can be found under http://pci-ids.ucw.cz/iii/ )
- The bus type , vendor , device and unique part identifiers are put together to create the modalias string which uniquely identifies the device and it's :make / model / version.
osslin7:/sys/bus/pci/devices/0000:01:00.0 # cat modalias
pci:v000014E4d00001677sv0000103Csd000012F2bc02sc00i00
- This modalias string is returned back to the udev daemon so that the correct driver module can be loaded.
- [5] Module configuration info is passed back to the udevd by hwup. ( this step is only to show that it is udevd that is running the show, not hwup.)
- first a little about modprobe as it's important.
- modprobe is used to load driver modules into the kernel. It's use is preferable over /sbin/insmod as it automatically resolves module dependencies ( as :listed in the /lib/modules/<kernel>/modules.dep file , which is created by the /sbin/depmod command.) }--
- if hwup used step [4b] modprobe will use the modalias string provided by hwup to find correct module from /lib/modules/<kernel_version>/modules.aliases e.g
- Remind ourselves of our modalias string for our network card.
cat /sys/bus/pci/devices/0000\:01\:00.0/modalias
pci:v000014E4d00001677sv0000103Csd000012F2bc02sc00i00
- The vendor and device type portion of this string point to one module from the modules.alias file ( luckily the same module (tg3) as specified in the :/etc/sysconfig/hardware/hwcfg-bus-pci-0000:01: 00.0 file!.)
grep v000014E4d00001677 /lib/modules/2.6.13-15.12-smp/modules.alias
alias pci:v000014E4d00001677sv*sd*bc*sc*i* tg3
- modprobe then loads the module taking into account settings from /etc/modprobe.conf
- /etc/modprobe.conf defines options and aliases for modules that are to be loaded. it also "includes" the contents of /etc/modprobe.conf.local and :/etc/modprobe.d
- also local changes should be made to /etc/modprobe.conf.local ( as they may otherwise be overwritten by patching.)
- The config files can also be used to "blacklist" a module , i.e prevent it from being loaded.
- [7] udevd creates /device tree and /dev tree device files for the newly configured hardware according to contents of /etc/udev/rules.d/*
unixspod@osslin5:/etc/udev/rules.d> ls
05-udev-early.rules 40-alsa.rules 60-cdrom_id.rules 65-cdrom.rules 85-mount-fstab.rules
29-net_trigger_firmware.rules 50-udev-default.rules 60-persistent-input.rules 71-multipath.rules 90-hal.rules
30-net_persistent_names.rules 51-lirc.rules 60-persistent-storage.rules 72-multipath-compat.rules 95-udev-late.rules
31-network.rules 56-idedma.rules 64-device-mapper.rules 80-sysconfig.rules
- The rules scripts are processed in order of the shell expansion , i.e in their numbered order. Many rules scripts provide persistent names so that :persistent device names remain regardless of the order in which devices are configured.
- For example:-
- Persistent storage device names are created.
- The device names /dev/hda /dev/hdb etc.. are assigned simply in the order they are discovered / configured. This is vulnerable to a hardware :reconfiguration ( say the inroduction of a IDE controller card ) which would affect the order of device discovery. To offer a solution to this problem :device files are also created that include disk specific device names. In the case of disks these device files can be found under /dev/disk
unixspod@osslin5:/> ls /dev/disk
by-id by-path by-uuid
- Where:-
- by-id contains device filenames based on the Vendor and Name of a device.
- by-path contains device filenames based on the bus position / path of a device.
- by-uuid contain device filenames based on the serial number of a device.
- Here are some rules that create the by-id device filenames for ata drives.
- <extract from /etc/udev/rules.d/60-persistent-storage.rules>
# by-id (hardware serial number) KERNEL=="hd*[!0-9]", IMPORT{program}="ata_id --export $tempnode" KERNEL=="hd*[!0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/ata-$env{ID_MODEL}_$env{ID_SERIAL}" KERNEL=="hd*[0-9]", SYMLINK+="disk/by-id/ata-$env{ID_MODEL}_$env{ID_SERIAL}-part%n"
- And here are the device filenames created ( together with their links to the plain device names. )
unixspod@osslin5:/> ls -l /dev/disk/by-id/
lrwxrwxrwx 1 root root 9 May 15 20:04 ata-WDC_WD800BB-75CAA0_WD-WMA8E8009441 -> ../../hda
lrwxrwxrwx 1 root root 10 May 15 20:04 ata-WDC_WD800BB-75CAA0_WD-WMA8E8009441-part1 -> ../../hda1
lrwxrwxrwx 1 root root 9 May 15 20:04 ata-WDC_WD800JD-60JR_WD-WMAMD2644033 -> ../../sda
lrwxrwxrwx 1 root root 10 May 15 20:04 ata-WDC_WD800JD-60JR_WD-WMAMD2644033-part1 -> ../../sda1
lrwxrwxrwx 1 root root 9 May 15 20:04 edd-int13_dev80 -> ../../sda
lrwxrwxrwx 1 root root 10 May 15 20:04 edd-int13_dev80-part1 -> ../../sda1
lrwxrwxrwx 1 root root 9 May 15 20:04 edd-int13_dev81 -> ../../hda
lrwxrwxrwx 1 root root 10 May 15 20:04 edd-int13_dev81-part1 -> ../../hda1
lrwxrwxrwx 1 root root 9 May 15 20:04 scsi-SATA_WDC_WD800JD-60J_WD-WMAMD2644033 -> ../../sda
llrwxrwxrwx 1 root root 10 May 15 20:04 scsi-SATA_WDC_WD800JD-60J_WD-WMAMD2644033-part8 -> ../../sda8
unixspod@osslin5 :/> ls -l /dev/disk/by-path/
lrwxrwxrwx 1 root root 9 May 15 20:04 pci-0000:00:1f.1-ide-0:0 -> ../../hda
lrwxrwxrwx 1 root root 10 May 15 20:04 pci-0000:00:1f.1-ide-0:0-part1 -> ../../hda1
lrwxrwxrwx 1 root root 9 May 15 20:04 pci-0000:00:1f.1-ide-1:0 -> ../../hdc
lrwxrwxrwx 1 root root 9 May 15 20:04 pci-0000:00:1f.2-scsi-0:0:0:0 -> ../../sda
lrwxrwxrwx 1 root root 10 May 15 20:04 pci-0000:00:1f.2-scsi-0:0:0:0-part1 -> ../../sda1
unixspod@osslin5:/> ls -l /dev/disk/by-uuid/
lrwxrwxrwx 1 root root 10 May 15 20:04 381d72cc-59f0-41ab-9c16-5166a938de92 -> ../../sda7
lrwxrwxrwx 1 root root 10 May 15 20:04 3bd1f095-3943-4fa0-9813-b8c4fdb0c42e -> ../../sda8
lrwxrwxrwx 1 root root 10 May 15 20:04 3c5d66a3-5476-4ab4-b01a-801f39b40b66 -> ../../hda1
lrwxrwxrwx 1 root root 10 May 15 20:04 5d3c4512-fd6e-4e70-bad2-3faf3a25ca25 -> ../../sda6
- Similiarly there are rules to tie a particular ethernet address to an interface name.
- <extract from 30-net_persistent_names.rules>
SUBSYSTEM=="net", ACTION=="add", SYSFS{address}=="00:12:79:de:f4:5d", IMPORT="/lib/udev/rename_netiface %k eth0"
- !!! This should be born in mind when changing a network card !!!
- udev informs applications of the new device through the Hardware Abstraction Layer ( HAL ).