#! /bin/sh # # start_udev # script to initialize /dev by using udev. # # Modified for Archlinux by Tobias Powalowski # Jan 16, 2006: Aaron Griffin # Optimize trigger_device_events loop. # # Inspired by: # # Copyright (C) 2004 Greg Kroah-Hartman # # Released under the GPL v2 only. # # This needs to be run at the earliest possible point in the boot # process. # # Based on the udev init.d script # # Thanks go out to the Gentoo developers for proving # that this is possible to do. # # Yes, it's very verbose, feel free to turn off all of the echo calls, # they were there to make me feel better that everything was working # properly during development... # # OpenSuse for the new uevents part prog=udev sysfs_dir=/sys bin=/sbin/udev udevd=/sbin/udevd udev_root="/dev" starttime=$(date +%s) #AMG: The /sys/class/tty uevents are very large in number # (583/737 uevents on this machine). Because this script # wants them to be triggered first, we'll trigger them # within the first therefore speeding up the ordering in # the second loop. The order has been verified to be # identical to the previous method. This has an added # benefit of starting the uevent triggering earlier. #NOTE: Further speed may be gained by backgrounding the echo calls # with the possible introduction of race conditions. function trigger_builtin_events() { list="$(echo /sys/class/*/*/uevent)" for i in $list; do case "$i" in */class/uevent|*\**) continue ;; */class/mem/*|*/class/tty/*) echo "add" > "$i" ;; esac done } function trigger_device_events() { list=$(echo /sys/bus/*/devices/*/uevent) list="$list $(echo /sys/class/*/*/uevent)" list="$list $(echo /sys/block/*/uevent /sys/block/*/*/uevent)" for i in $list; do case "$i" in */device/uevent|*\**) continue ;; */block/md*) last="$last $i" ;; */*) default="$default $i" ;; esac done # trigger the sorted events for i in $default $last; do echo "add" > "$i" done } function wait_for_queue() { loop=20 while ! [ "$loop" -gt 0 -a -d /dev/.udev/queue ]; do sleep 0.1; loop=$(($loop - 1)) done loop=200 while [ "$loop" -gt 0 -a -d /dev/.udev/queue ]; do sleep 0.1; loop=$(($loop - 1)) done } make_extra_nodes () { # there are a few things that sysfs does not export for us. # these things go here (and remember to remove them in # remove_extra_nodes() # # Thanks to Gentoo for the initial list of these. ln -snf /proc/self/fd $udev_root/fd ln -snf /proc/self/fd/0 $udev_root/stdin ln -snf /proc/self/fd/1 $udev_root/stdout ln -snf /proc/self/fd/2 $udev_root/stderr ln -snf /proc/kcore $udev_root/core mkdir $udev_root/pts mkdir $udev_root/shm } udev_init () { # don't use udev if sysfs is not mounted. if [ ! -d $sysfs_dir/block ]; then exit 1 fi echo "mounting... ramfs at $udev_root" mount -n -t ramfs none $udev_root # propogate /udev from /sys echo "Creating initial udev device nodes:" #echo "making extra nodes" make_extra_nodes # check if udevd is already running if [ `pidof -o %PPID /sbin/udevd` ]; then grep -v "/dev/shm" /etc/mtab | grep -v "/dev/pts" > /etc/mtab mount /dev/pts mount /dev/shm else echo "start udev daemon" /sbin/udevd --daemon fi case "$(uname -r)" in 2.6.[0-9]|2.6.[0-9][!0-9]*) ;; *) if [ -f "/sys/class/tty/console/uevent" ]; then echo "Kernel >= 2.6.15 and supports uevents" # trigger the sorted events echo -e '\000\000\000\000' > /proc/sys/kernel/hotplug # catch events that a real fast mkdir -p /dev/.udev/queue trigger_builtin_events else # for older kernels without uevents will be removed when udevstart dies in udev echo "Kernel does not support uevents, you need a kernel >= 2.6.15!" exit 1 fi ;; esac } udev_uevents () { # configure all devices trigger_device_events # until we know how to do better, just wait for _all_ events to finish wait_for_queue } if [ $# -eq 0 ]; then udev_init udev_uevents fi [ "$1" = "init" ] && udev_init [ "$1" = "uevents" ] && udev_uevents echo "udev startup is finished! - time = $(( `date +%s` - $starttime ))" exit 0