X-Git-Url: http://git.pld-linux.org/?a=blobdiff_plain;f=start_udev;h=bf64dc55b3135c427e04ba82fc25514a97f844f9;hb=ca35649fa718039aaf8630e6730b89f981c2adcf;hp=7d1e0bd0d94c02351da3e8a5e9d1c01224ea925f;hpb=559728728e255ee0b0b9036f6b12258cb3286187;p=packages%2Fsystemd.git diff --git a/start_udev b/start_udev old mode 100644 new mode 100755 index 7d1e0bd..bf64dc5 --- a/start_udev +++ b/start_udev @@ -8,90 +8,168 @@ # # Released under the GPL v2 only. # -# This needs to be run at the earliest possible point in the boot +# 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 +# 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... -# + +# default value, if no config present. +udev_root="/dev" +sysfs_dir="/sys" +udevd_timeout=8 + # don't use udev if sysfs is not mounted. -[ ! -d $sysfs_dir/class ] || exit 1 +[ -d $sysfs_dir/class ] || exit 1 [ -r /proc/mounts ] || exit 1 -[ -x /sbin/udev ] || exit 1 [ -f /etc/udev/udev.conf ] && . /etc/udev/udev.conf - . /etc/rc.d/init.d/functions prog=udev -sysfs_dir=/sys bin=/sbin/udev -udevd=/sbin/udevd -MAKEDEV="/sbin/MAKEDEV" - -make_extra_nodes () { - 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 - - [ -d $udev_root/pts ] || (mkdir $udev_root/pts;chmod 0755 $udev_root/pts) - [ -d $udev_root/shm ] || (mkdir $udev_root/shm;chmod 0755 $udev_root/shm) - - if [ -x $MAKEDEV ]; then - $MAKEDEV -x $( - for i in 0 1 2 3 4 5 6 7; do echo fd$i; done - for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do - echo cpu/$i/microcode; - done; - for i in 0 1 2 3 4 5 6 7; do echo loop$i; done - for i in 0 1 2 3; do echo lp$i; echo par$i;done - echo net/tun ppp; - ); - [ -a /dev/MAKEDEV ] || ln -s $MAKEDEV /dev/MAKEDEV; +udevd=/lib/udev/udevd +# trim traling slash, code expects it not to be there +udev_root=${udev_root%/} + +create_static_nodes() { + /sbin/kmod static-nodes --format=tmpfiles | \ + while read type file mode uid gid age dev ; do + case $type in + d|D) + mkdir -p --mode=$mode $file + ;; + *) + oldIFS=$IFS + IFS=":" + set -- $dev + maj=$1 + min=$2 + IFS=$oldIFS + mknod --mode=$mode $file $type $maj $min + ;; + esac + [ $uid = "-" ] || chown $uid $file + [ $gid = "-" ] || chgrp $gid $file + done +} + +make_extra_nodes() { + grep '^[^#]' /etc/udev/links.conf | \ + while read type name arg1; do + [ "$type" -a "$name" -a ! -e "$udev_root/$name" -a ! -L "/dev/$name" ] ||continue + case "$type" in + L) ln -s $arg1 $udev_root/$name ;; + D) mkdir -p $udev_root/$name ;; + M) mknod -m 600 /dev/$name $arg1 ;; + *) echo "links.conf: unparseable line ($type $name $arg1)" ;; + esac + done + [ -d /lib/udev/devices ] && cp -a /lib/udev/devices/* /dev/ >/dev/null 2>&1 || : + [ -d /lib64/udev/devices ] && cp -a /lib64/udev/devices/* /dev/ >/dev/null 2>&1 || : +} + +kill_udevd() { + if [ -x /sbin/pidof ]; then + pid=$(/sbin/pidof -x udevd) + [ -n "$pid" ] && kill $pid fi } -mount_udev() { - [ -e "/selinux/enforce" ] && mountopt=",fscontext=system_u:object_r:device_t" - mount -n -o mode=0755${mountopt} \ - -t tmpfs none "$udev_root" - return $? +set_hotplug_handler() { + echo "" > /proc/sys/kernel/hotplug } +# find subdirs mounted under $udev_root +get_dev_mounts() { + awk -vudev_root="$udev_root/" ' + BEGIN { + len = length(udev_root); + } + + substr($2, 1, len) == udev_root { + print substr($2, len + 1) + }' /proc/mounts +} + +show "Starting udev"; busy + +export ACTION=add +prog=udev +ret=0 + +# mount the devtmpfs on $udev_root, if not already done +awk "\$2 == \"$udev_root\" && \$3 == \"devtmpfs\" { exit 1 }" /proc/mounts && { + submounts=$(get_dev_mounts) -grep -q " ${udev_root%/} " /proc/mounts || { - echo -n "Mouting tmpfs at $udev_root" - if (mount_udev); then - deltext - ok + if [ "$submounts" ]; then + # mount to temporary location to be able to move submounts + # this needs writable TMPDIR:-/tmp, so it won't work in early boot + # but fix is simple: use initramfs instead of romfs + devdir=$(mktemp -d ${TMPDIR:-/tmp}/tmpXXXXXX) else - deltext - fail + devdir=$udev_root + fi + mount -n -o mode=0755 -t devtmpfs devtmpfs "$devdir" + ret=$(( $ret + $? )) + + # relocate submounts + for dir in $submounts; do + mount -n --move $udev_root/$dir $devdir/$dir + ret=$(( $ret + $? )) + done + + if [ "$submounts" ]; then + mount -n --move $devdir $udev_root + rmdir $devdir fi } - -echo -n "Making extra nodes" -if (make_extra_nodes); then - deltext - ok +kill_udevd > "$udev_root/null" 2>&1 + +# Create required static device nodes for the current kernel +create_static_nodes + +# Start udevd daemon +$udevd --daemon; rc=$? +test $rc -eq 0 && ok || fail +ret=$(( $ret + $rc )) + +# Making extra nodes +show "Setup extra nodes"; busy +make_extra_nodes; rc=$? +test $rc -eq 0 && ok || fail +ret=$(( $ret + $rc )) + +if [ -f /sys/class/tty/console/uevent ]; then + # Setting default hotplug handler + set_hotplug_handler + ret=$(( $ret + $? )) + + # retrigger all events + show "Retrigger subsystems events"; busy + /sbin/udevadm trigger --type=subsystems --action=add; rc=$? + test $rc -eq 0 && ok || fail + ret=$(( $ret + $rc )) + + show "Retrigger devices events"; busy + /sbin/udevadm trigger --type=devices --action=add; rc=$? + test $rc -eq 0 && ok || fail + ret=$(( $ret + $rc )) + + # wait for the events to finish + show "udevadm settle"; busy + /sbin/udevadm settle; rc=$? + test $rc -eq 0 && ok || fail + ret=$(( $ret + $rc )) else - deltext - fail + echo "Kernel too old for this udev version" fi -export ACTION=add -export UDEV_NO_SLEEP=1 -# propagate $udev_root from /sys -rm -f $udev_root/.udev.tdb -run_cmd "Starting udev" /sbin/udevstart - -exit 0 +exit $ret